Marklar
Marklar

Reputation: 1056

KnockoutJS observable arrays with computed observables

I have a JSON array, two lists (populated by a computed observable) and an array of selected items (ids of items in the JSON array).

The selected items are held in an observableArray and I want one list to be populated with items that are in the array and the other to be populated by all of the items that aren't in the array.

This works fine on initialisation but then if I try to add items to the selected items array, the changes aren't reflected in the UI or in the two list arrays.

https://jsfiddle.net/mnbu21z4/3/

var witnessJSON = [
    {"id":3,"name":"Bob3"},
    {"id":2,"name":"Bob2"},
    {"id":1,"name":"Bob1"}
];

var viewModel = function() {
  self = this;

  self.witnessArray = ko.observableArray([1]);

  self.witnessesAdded = ko.computed(function() {
    return ko.utils.arrayFilter(witnessJSON, function(witness) {
      return self.witnessArray().indexOf(witness.id) > -1;
    });
  });

  self.witnessesPool = ko.computed(function() {
    return ko.utils.arrayFilter(witnessJSON, function(witness) {
      return self.witnessArray().indexOf(witness.id) == -1;
    });
  });
}

myViewModel = new viewModel();
ko.applyBindings(myViewModel);

viewModel.witnessArray.push(2);

Can someone point me in the right direction?

Upvotes: 1

Views: 64

Answers (1)

Anish Patel
Anish Patel

Reputation: 4402

It appears that you have misspelled myViewModel further down in your example.

Change this:

myViewModel = new viewModel();
ko.applyBindings(myViewModel);

viewModel.witnessArray.push(2);

To this:

var myViewModel = new viewModel();
ko.applyBindings(myViewModel);

myViewModel.witnessArray.push(2);

And then your fiddle example will work. I've made these changes and updated your fiddle, it works.

You may want to look into the knockout projections plugin, it allows you to achieve the same thing in a more efficient way. Take a look at this SO answer

Upvotes: 1

Related Questions