我有一个shoppingcart
视图模型,其中包含observableArray
个cartitems
视图模型。
当我更新subtotal
视图模型的cartitems
属性时,我的shoppingcart
viewmodel上的computedObservable需要更新,但我不知道如何让它触发更新
function shoppingcart() {
var self = this;
self.cartItems = ko.observableArray([]);
self.grandTotal = ko.computed(function() {
var total = 0;
_.each(self.cartItems(), function (item) {
total += item.subTotal;
}
}
//inital load of the data
dataservice.loadCartItems(self.cartItems);
}
function cartItem() {
var self = this;
self.quantity = ko.observable(0);
self.price = 0.00;
self.subTotal = ko.computed(function() {
return self.price * self.quantity();
}
}
然后在我看来,我有类似的东西
<ul data-bind='foreach: cartItems'>
<!--other stuff here -->
<input type='text' data-bind="value: quantity, valueUpdate: 'afterkeydown'"/>
</ul>
<span data-bind='value: grandTotal'></span>
这假设是否正常工作,我只是搞砸了某个地方,或者我是否需要添加其他内容才能更新?
现在,当文本框中的数量发生变化时,不会更新跨度中的grandTotal。我假设它是因为这个子属性实际上并不算作cartItems集合被更改。
在这里触发更新集合的好方法是什么?
答案 0 :(得分:2)
您没有从grandTotal
计算中返回任何内容。此外,您尝试将subTotal
函数添加到正在运行的total
而不是其返回值。您需要使用括号调用才能调用cartItem
上的计算。
function shoppingcart() {
var self = this;
self.cartItems = ko.observableArray([]);
self.grandTotal = ko.computed(function() {
var total = 0;
_.each(self.cartItems(), function (item) {
total += item.subTotal(); // need parenthesis to invoke
}
return total; // return a value, otherwise function is void
}
//inital load of the data
dataservice.loadCartItems(self.cartItems);
}
function cartItem() {
var self = this;
self.quantity = ko.observable(0);
self.price = 0.00;
self.subTotal = ko.computed(function() {
return self.price * self.quantity();
}
}
答案 1 :(得分:1)
因此,如果我理解正确,主要问题是当其中一个元素发生变化时,您需要触发observableArray变异。它可以做到,但我不知道这是否是最好的做法。有关替代实施的信息,请参阅此内容:Observable notify parent ObservableArray
此小提琴的示例解决方案手动调用valueHasMutated:http://jsfiddle.net/F6D6U/6/
HTML:
<ul data-bind='foreach: cartItems'>
<!--other stuff here -->
<input type='text' data-bind="value: quantity, valueUpdate: 'afterkeydown'"/>
* <span data-bind="text:price"></span>
= <span data-bind="text:subTotal"></span>
<br />
</ul>
<span data-bind='text: grandTotal'></span>
JS:
function cartItem(q, p, a) {
var self = this;
self.quantity = ko.observable(q);
self.price = p;
self.parentArray = a;
self.subTotal = ko.computed(function() {
var subtotal = parseFloat(self.price,10) * parseFloat(self.quantity(),10);
self.parentArray.valueHasMutated();
return subtotal;
},self);
}
function shoppingcart() {
var self = this;
self.cartItems = ko.observableArray();
self.cartItems([
new cartItem(10,100, self.cartItems),
new cartItem(1,3, self.cartItems),
]);
self.grandTotal = ko.computed(function() {
var total = 0;
ko.utils.arrayForEach(self.cartItems(), function (item) {
total += item.subTotal();
});
return total;
}, self);
//inital load of the data
//dataservice.loadCartItems(self.cartItems);
}
ko.applyBindings(new shoppingcart())