1
votes

In my view model, I have an observable array that needs to be populated from a $.getJSON call. I would like to have a computed observable to represent the total of a "price" column contained in the JSON returned.

I've managed to populate the observable array...

(function($){

    function Coupon(expiration, value) {
        var self = this;
        self.expiration = expiration;
        self.value = value;
    }

    $(function() {
        $.when($.getJSON(coupons_url, null)).done(function(couponsJson) {
            ko.applyBindings({
                coupons: ko.utils.arrayMap(couponsJson[0].objects,
                    function(coupon) {
                        return new Coupon(coupon.expiration, coupon.value);
                    })

                savingsAvailable: ko.computed(function() {
                    var total = 0;
                    for (var i = 0; i < this.coupons().length; i++) {
                        total += parseFloat(this.coupons()[i].value / 100);
                    }
                    return total.toFixed(2);
                })
            });
        });

    });
})(jQuery);

...but I'm not sure how to then access the value of coupons when I try to populate the computed observable. this.coupons() errors out: "this.coupons() is not a function". What do I need to do to accomplish this, and/or what am I doing wrong?

1
I am not 100% what exactly you are trying to accomplish but this inside your computed no longer refers to your view model. I don't understand the syntax of your JavaScript because I have never written it this way. - PW Kad
I got it figured out and will post an update to my answer shortly. Thanks for taking the time to look at my question. - Brandon

1 Answers

1
votes

ko.computed() takes a second parameter that defines the value of "this" when evaluating the computed observable. So what ever object hold "coupons" you would want to pass that in as the second parameter.

Or you could try something like the following create a view model instead of defining the object on the fly and passing it as a parameter to applyBindings.

var Coupon = function(expiration, value) {
    var self = this;
    self.expiration = expiration;
    self.value = value;

}

var viewModel = function(couponsJson){

    var self = this;

    self.coupons = ko.utils.arrayMap(couponsJson[0].objects, function(coupon) {
        return new Coupon(coupon.expiration, coupon.value);
    })

    self.savingsAvailable = ko.computed(function() {
        var total = 0;
        for (var i = 0; i < self.coupons().length; i++) {
                total += parseFloat(self.coupons()[i].value / 100);
        }
        return total.toFixed(2);
    })                                              

}


(function($){
    $(function() {
        $.when($.getJSON(coupons_url, null)).done(function(couponsJson) {
            var vm = new viewModel(couponsJson)
            ko.applyBindings(viewModel);
        });

    });
})(jQuery);