Reevaluating computed observables
by rniemeyer
HTML
<script src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<ul data-bind="foreach: highPriorityItems">
<li>
<span data-bind="text: name"></span>
</li>
</ul>
<button data-bind="click: addNewDataBad">Add New Bad</button>
<button data-bind="click: addNewDataGood">Add New Good</button>
<button data-bind="click: addNewData">Add New Simplified</button>
<hr />
Reevaluation Count: <span data-bind="text: highPriorityItems.reevaluationCount"></span>
CSS
ul { margin-left: 10px; }
a { text-decoration: none; }
JavaScript
//track the number of re-evaluations for a computed observable
ko.dependentObservable.fn.trackReevaluations = function() {
this.reevaluationCount = ko.observable(0);
this.subscribe(function() {
this.reevaluationCount(this.reevaluationCount() + 1);
}, this);
return this;
};
var newData = [
{ name: "Task Four", priority: "normal" },
{ name: "Task Five", priority: "high" },
{ name: "Task Six", priority: "high" },
{ name: "Task Seven", priority: "normal" },
{ name: "Task Eight", priority: "high" }
];
var Item = function(name, priority) {
this.name = ko.observable(name);
this.priority = ko.observable(priority);
};
var ViewModel = function() {
var self = this;
this.items = ko.observableArray([
new Item("Task One", "high"),
new Item("Task Two", "normal"),
new Item("Task Three", "high")
]);
this.highPriorityItems = ko.computed(function() {
return ko.utils.arrayFilter(this.items(), function(item) {
return item.priority() === "high";
});
}, this).trackReevaluations();
this.addNewDataBad = function(data) {
var item;
for (var i = 0, j = newData.length; i < j; i++) {
item = newData[i];
self.items.push(new Item(item.name, item.priority));
}
};
this.addNewDataGood = function() {
var item, underlyingArray = self.items();
for (var i = 0, j = newData.length; i < j; i++) {
item = newData[i];
underlyingArray.push(new Item(item.name, item.priority));
}
self.items.valueHasMutated();
};
//simplified
this.addNewData = function() {
var newItems = ko.utils.arrayMap(newData, function(item) {
return new Item(item.name, item.priority);
});
//take advantage of push accepting variable arguments
...