You need to unwrap your observable:
totalCost: ko.computed(function () {
//also, you forgot typeof below
if (typeof gifts == 'undefined')
return 0;
var total = 0; //here \/
for (var i=0; i < gifts().length; i++)
{ //and here \/
total += parseFloat(gifts()[i].Price());
};
return total;
})
The reason it's not updating, is because
gifts.length
is always evaluating to 0
, and never entering the loop. And even if it did,
gifts[i].Price()
would not work for the same reason; you need to unwrap the observable.
Note that the reason why length evaluates to zero when you don't unwrap it is because you're getting the length of the actual observable array function. All observables in Knockout are implemented as regular functions; when you don't unwrap it, you're hitting the actual function itself, not the underlying array.
Edit,
Also, you need to reference gifts with this.gifts
, since it's an object property. That's why this wasn't working; gifts is always undefined.
That said, you also need to do some more work to get ko computeds to work from an object literal. Read here for more info:
http://dpruna.blogspot.com/2013/09/how-to-use-kocomputed-in-javascript.html
Here's how I would make your view model:
function Vm{
this.gifts = ko.observableArray(); // gifts will be an array of Gift classes
this.addGift = function () {
this.gifts.push(new Gift({ Title: "", Price: "" }));
};
this.removeGift = function (gift)
{
this.gifts.remove(gift);
};
this.totalCost = ko.computed(function () {
var total = 0;
for (var i = 0; i < this.gifts().length; i++)
{
total += parseFloat(this.gifts()[i].Price());
};
return total;
}, this);
}
var viewModelForTemplated = new Vm();