Reputation: 53
I have a Collection of items that I would like to display the Total as well as individual Percentage of each item. The problem seems to be that I need a reference of parent object when computing the total. So I figured I'll define a computed getTotal for the Collection and a percentage for the item.
function Collection() {
var self = this;
self.parts = ko.observableArray();
self.getTotal = ko.computed(function() {
var total = self.parts.length;
return total;
});
}
function Part(amount, parent) {
var self = this;
self.amount = ko.observable(amount);
self.parent = parent;
self.percentage = ko.computed(function() {
return self.amount() / self.parent.getTotal();
});
}
var partsData = [40, 50, 30];
var collection = new Collection();
for (var i = 0; i < partsData.length; ++i) {
collection.parts.push(new Part(partsData[i], collection));
}
ko.applyBindings(collection);
And my HTML is
<ul data-bind="foreach: parts">
<li>
<p data-bind="text: amount"></p>
<p data-bind="text: percentage"></p>
</li>
</ul>
However the Collection.parts is always empty. For some reason push it not triggering the items to be recalculated.
Also is this the right way for doing this? I could now figure out how I could simultaneously create an observableArray in the Collection while giving each child item a reference to the parent object.
Upvotes: 3
Views: 2813
Reputation: 9361
function ViewModel() { var self = this; self.parts = ko.observableArray([]); self.total = ko.computed(function(){ var s = 0; $.each(self.parts(), function(i, el){s += el.amount();}); return s; }); } function Part(amount){ this.amount = ko.observable(amount); } $(function() { var view = new ViewModel(); var parts = $.map([40, 50, 30], function(el){return new Part(el);}); view.parts(parts); ko.applyBindings(view); });
Html:
<ul data-bind="foreach: parts()">
<li>
<p data-bind="text: amount"></p>
<p data-bind="text: amount() / $root.total()"></p>
</li>
</ul>
Upvotes: 6