Andrew Andrew - 5 months ago 22
Javascript Question

Get length of property after destroying element in KnockoutJS

In KnockoutJS you can have a property that is an array of objects. Eg.

self.items
could be made up of items:

var item = function (data){
//mapping here
}


You can then "destroy" one of those objects by calling something like:

self.items.destroy(item);


But then if I check/bind to the length of self.items, it is still the full length (including destroyed objects). Eg, this won't get updated properly after destroying stuff, and stays visible:

data-bind="visible: myData.items().length > 0"


How to get the length, minus the destroyed objects?

I suppose I could create a
computed
kojsLength method and add it to every object, that loops over the array and counts all items that don't have the
_destroy
property?

But is there a built in KOJS solution, or do I have to do this?

Edit, my solution:

For me, since I have no use for the _destroy property on the back end, directly substituting in the
remove
function for
destroy
works perfect.

Answer

That is because destroyed elements are not actually removed from the underlying array. They are just marked as destroyed, as you can see by running the below snippet.

There is no built-in KO solution for that.

If you want to exclude them by computing length, you need a custom length function which discards them:

function viewModel(name) {
  this.name = name;
}


var array = ko.observableArray([new viewModel("a"), new viewModel("b")]);

console.log(array().length);

array.destroy(array()[0]);
console.log(array().length);
console.log(JSON.stringify(array()));


function lengthOfAlive(obs) {
  var before = obs().length;
  var res = before;
  for (var i = 0; i < before; ++i) {
    if (obs()[i]._destroy)
      res--;
  }
  return res;
}

console.log(lengthOfAlive(array));
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>

Comments