Suppose you have the following js:
var vm = {
objects: ko.observable([]),
objectCount: ko.computed(function(){
return vm && vm.objects().length;
}),
add: function() {
var current = vm.objects();
current.push({});
console.log('current is', current);
vm.objects(current);
console.log("should recalculate here", vm.objectCount());
}
};
And the following html:
<ul data-bind="foreach: objects">
<li>
Object: <span data-bind="text: $index"></span>
</li>
</ul>
<button data-bind="click: add">Add Object</button>
<p>
Total number of objects:
<span data-bind="text: objectCount"></span>
</p>
It is my understanding from reading the documentation that because after I add an object I call objectCount(), that it should recalculate its dependencies. Instead it seems to never even execute the function, running it only once!
It's just a scoping issue. If you refactor your script code to look like this:
$(function(){
var vm = function(){
var self = this;
self.objects = ko.observable([]);
self.objectCount = ko.computed(function(){
return self.objects().length;
});
self.add = function() {
var current = self.objects();
current.push({});
console.log('current is', current);
self.objects(current);
console.log("should recalculate here", self.objectCount());
};
};
ko.applyBindings(new vm());
});
Then the correct variables are scoped and Knockout correctly calculates the dependencies. As stated by guigouz, when ko.computed
is initially called, vm
is undefined, so it cannot setup any change handlers.
Here is the updated JSBin