knockout.js - Select items based on values in Observable array -
i have select menu list contains available approval levels (self.approvallevels observable array).
i have ordered list contains 3 selected approval levels (self.userselectedapprovallevels observable array). these sorted priority.
i want items in self.userselectedapprovallevels observable marked selected in select menu list.
how do this?
var viewmodel = function() { var self = this; self.approvallevels = ko.observablearray([]); // observable array store list of available approval levels self.userselectedapprovallevels = ko.observablearray([]); // observable array store list of approval levels selected user self.approvallevels = ko.observablearray([{ "approvallevelid": 1, "approvallevelname": "analyst" }, { "approvallevelid": 2, "approvallevelname": "supervisor" }, { "approvallevelid": 3, "approvallevelname": "tester" }, { "approvallevelid": 4, "approvallevelname": "manager" } ]); self.userselectedapprovallevels = ko.observablearray([{ "approvallevelid": 2, "approvallevelname": "supervisor", "approvallevelpriority": 0 }, { "approvallevelid": 1, "approvallevelname": "analyst", "approvallevelpriority": 1 }, { "approvallevelid": 3, "approvallevelname": "tester", "approvallevelpriority": 2 } ]); }; ko.applybindings(new viewmodel()); <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <div class="row"> <div class="col-lg-6"> <div class="form-group"> <label for="approvallist">select approval level(s)</label> <select multiple="multiple" class="form-control" id="approvallevellist" data-bind="options: approvallevels, selectedoptions: userselectedapprovallevels, optionstext: 'approvallevelname', optionsvalue: 'approvallevelname'"></select> <small id="approvallevellist" class="form-text text-muted">select approval levels required task.</small> </div> </div> <div class="col-lg-6"> <p>sort in order of approval level (highest lowest):</p> <ol id="selectedapprovallevelslist" data-bind="foreach: userselectedapprovallevels"> <li class="list-group-item-info"> <span data-bind="text: approvallevelname"> </span> </li> </ol> </div> </div>
for selections correctly linked, need either reference same objects, or reference primitive can compared using ===.
my advice create source objects once, inside self.approvallevels. set initial selection, add references items in array selectedapprovallevels so:
self.userselectedapprovallevels = ko.observablearray([ self.approvallevels()[0], self.approvallevels()[1], self.approvallevels()[2] ]); now, selected list not sorted, correctly synced.
to sort list, create additional computed layer takes selections , re-arranges them:
self.sortedsal = ko.purecomputed(function() { return self.userselectedapprovallevels().sort(function(a, b) { return a.approvallevelpriority - b.approvallevelpriority; }); }); i put in working example below.
var viewmodel = function() { var self = this; self.approvallevels = ko.observablearray([]); // observable array store list of available approval levels self.userselectedapprovallevels = ko.observablearray([]); // observable array store list of approval levels selected user self.approvallevels = ko.observablearray([ { "approvallevelid": 1, "approvallevelname": "analyst", "approvallevelpriority": 1 }, { "approvallevelid": 2, "approvallevelname": "supervisor", "approvallevelpriority": 0 }, { "approvallevelid": 3, "approvallevelname": "tester", "approvallevelpriority": 2 }, { "approvallevelid": 4, "approvallevelname": "manager", "approvallevelpriority": 2 } ]); self.userselectedapprovallevels = ko.observablearray( // initial selections: self.approvallevels().slice(0, 3) ); self.sortedsal = ko.purecomputed(function() { return self.userselectedapprovallevels().sort(function(a, b) { return a.approvallevelpriority - b.approvallevelpriority; }); }); }; ko.applybindings(new viewmodel()); <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <div class="row"> <div class="col-lg-6"> <div class="form-group"> <label for="approvallist">select approval level(s)</label> <select multiple="multiple" class="form-control" id="approvallevellist" data-bind="options: approvallevels, selectedoptions: userselectedapprovallevels, optionstext: 'approvallevelname', optionsvalue: 'approvallevelname'"></select> <small id="approvallevellist" class="form-text text-muted">select approval levels required task.</small> </div> </div> <div class="col-lg-6"> <p>sort in order of approval level (highest lowest):</p> <ol id="selectedapprovallevelslist" data-bind="foreach: sortedsal"> <li class="list-group-item-info"> <span data-bind="text: approvallevelname"> </span> </li> </ol> </div> </div> edit concerning requirement of 2 separate plain object lists
if you're retrieving 2 lists server, it's best create client-side viewmodel combines data need together. can use <select>'s list main source, , add computed sortorder properties based on second list:
sortorder: ko.purecomputed(function() { var match = apsortdata().find(function(item) { return item.approvallevelid === data.approvallevelid; }); return match ? match.approvallevelpriority : 0; }) in working example, in sort order data comes in 1 second after source information:
var viewmodel = function() { var self = this; var apsortdata = ko.observablearray([]); settimeout(function() { // show linked automatically apsortdata(getsortorderdata()); }, 1000) var approvallevelvm = function(data) { return object.assign( {}, data, { sortorder: ko.purecomputed(function() { var match = apsortdata().find(function(item) { return item.approvallevelid === data.approvallevelid; }); return match ? match.approvallevelpriority : 0; }) } ); }; self.approvallevels = ko.observablearray( getapprovalleveldata().map(approvallevelvm) ); self.userselectedapprovallevels = ko.observablearray( // initial selections: self.approvallevels().slice(0, 3) ); self.sortedsal = ko.purecomputed(function() { return self.userselectedapprovallevels() .sort(function(a, b) { return a.sortorder() - b.sortorder(); }); }).extend({"deferred": true}); }; ko.applybindings(new viewmodel()); function getapprovalleveldata() { return [{ "approvallevelid": 1, "approvallevelname": "analyst" }, { "approvallevelid": 2, "approvallevelname": "supervisor" }, { "approvallevelid": 3, "approvallevelname": "tester" }, { "approvallevelid": 4, "approvallevelname": "manager" } ]; }; function getsortorderdata() { return [{ "approvallevelid": 2, "approvallevelname": "supervisor", "approvallevelpriority": 0 }, { "approvallevelid": 1, "approvallevelname": "analyst", "approvallevelpriority": 1 }, { "approvallevelid": 3, "approvallevelname": "tester", "approvallevelpriority": 2 } ]; } <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet" /> <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script> <div class="row"> <div class="col-lg-6"> <div class="form-group"> <label for="approvallist">select approval level(s)</label> <select multiple="multiple" class="form-control" id="approvallevellist" data-bind="options: approvallevels, selectedoptions: userselectedapprovallevels, optionstext: 'approvallevelname', optionsvalue: 'approvallevelname'"></select> <small id="approvallevellist" class="form-text text-muted">select approval levels required task.</small> </div> </div> <div class="col-lg-6"> <p>sort in order of approval level (highest lowest):</p> <ol id="selectedapprovallevelslist" data-bind="foreach: sortedsal"> <li class="list-group-item-info"> <span data-bind="text: approvallevelname + ' - '+ sortorder()"> </span> </li> </ol> </div> </div>
Comments
Post a Comment