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

Popular posts from this blog

javascript - Create a stacked percentage column -

Optimising Firebase database by automatically overwriting data -

javascript - Angular UI-Grid customTemplate directive causing rows to load slowly/? -