nthapa13 nthapa13 - 12 days ago 7
Javascript Question

Using ko.utils.arrayForEach to iterate over a observableArray

I am trying to calculate sum of 'price' field of an 'observableArray'. I have the following code so far:

(function(){

function objFeatures(name,price) {
return {
name: ko.observable(name),
price: ko.observable(price),

removeFeatures: function () {
appViewModel.features.remove(this);
}
}
}

var appViewModel = {
features: ko.observableArray([
new objFeatures("Feature1", 20),
new objFeatures("Feature2", 20)
]),

grandTotal: ko.computed(function () {
var total = 0;
ko.utils.arrayForEach(this.features(), function () {
total += this.price();
})
return total;
})
};

ko.applyBindings(appViewModel);

}());


When I try to run this, i get an "Error: this.features is not a function" in the firebug console.

What am i doing wrong?

Answer

Computed observables are evaluated immediately during creation. In your case, appViewModel has not been created yet and this will not represent the appViewModel.

There are many ways to ensure that this is correct in this case. Here are two:

  1. Create it outside of your initial object literal:

    var appViewModel = {
       features: ko.observableArray([
           new objFeatures("Feature1", 20),
           new objFeatures("Feature2", 20)
           ])
    };
    
    appViewModel.grandTotal = ko.computed(function() {
        var total = 0;
        ko.utils.arrayForEach(this.features(), function(feature) {
            total += feature.price();
        });
    
        return total;
    }, appViewModel);
    
  2. Create your view model in a function:

    var AppViewModel = function() {
        this.features = ko.observableArray([
            new objFeatures("Feature1", 20),
            new objFeatures("Feature2", 20)
        ]);
    
        this.grandTotal = ko.computed(function() {
            var total = 0;
            ko.utils.arrayForEach(this.features(), function(feature) {
                total += feature.price();
            });
            return total;
        }, this);
    };
    
    ko.applyBindings(new AppViewModel());‚Äč
    
Comments