Reputation: 4528
I'm learning knockoutjs, so please bear with me...
Take this code:
HTML:
<div id="itemsContainer">
</div>
<div id="cartContainer">
<label data-bind="text: totals"></label>
</div>
<div id="items"></div>
Javacript:
function ItemsViewModel() {
var self = this;
self.items = ko.observableArray().publishOn("items");
self.items.push({
count: 2,
price: 100
});
self.items.push({
count: 3,
price: 200
});
}
function CartViewModel() {
var self = this;
self.totals = ko.computed(function() {
var total = 0;
$.each(self, function(i, m) {
total = total + (m.count * m.price);
});
return total;
}, this).subscribeTo("items", true);
}
var itemsVM;
var cartVM;
itemsVM = new ItemsViewModel();
ko.applyBindings(itemsVM, document.getElementById("itemsContainer"));
cartVM = new CartViewModel();
ko.applyBindings(cartVM, document.getElementById("cartContainer"));
I want to update the "totals" depending on the data I put into (or change) in the ItemsViewModel.items.
I'm stuck now and have no idea how to make it work?
Upvotes: 4
Views: 125
Reputation: 23372
I'm not sure if subscribeTo
works on a computed like you've tried... A quick fix would be to create a (private) mirror inside the CartViewModel
constructor and use that in your computed
:
function CartViewModel() {
var self = this;
var allItems = ko.observableArray([]).subscribeTo("items", true);
self.totals = ko.computed(function() {
return allItems().reduce(function(total, m) {
return total + (m.count * m.price);
}, 0);
});
}
Note: I've replaced your $.each
with an Array.prototype.reduce
;)
Edit: I've found another answer in the docs: you can use a transform function:
function CartViewModel() {
var self = this;
self.totals = ko.observableArray([])
.subscribeTo("items", true, function(items) {
return items.reduce(function(total, m) {
return total + (m.count * m.price);
}, 0);
});
};
Updated fiddle with mirror approach: http://jsfiddle.net/qzLkjLL1/
Updated fiddle with transform approach: http://jsfiddle.net/ynoc6hha/
Upvotes: 3