javascriptknockout.jscomputed-observable

Knockoutjs - Reference local fields in computed observable


I'm new to KO and having trouble getting a computed value to work. I've got a viewmodel made up of many objects because I have many different tables in the database that I'm retrieving data from. This is an example of how I set the VM up. Feel free to critique anything I'm doing wrong in here (although it does work apart from the computed value):

var viewModel = function(object1, object2...) {
    var self = this;
    var activeProductCodes = ['AB-1', 'AB-2', 'AB-3'];

    self.myFirstObject = ko.observable({
        field1: ko.observable(object1.field1),
        field2: ko.observable(object1.field2),
        field3: ko.observable(object1.field3)
    });


    self.mySecondObject = ko.observable({
        productCode: ko.observable(object2.productCode),

        isActiveProduct: ko.computed(function() {
            return self.activeProductCodes.indexOf(productCode) !== -1 ? true : false;
        }, self)
    });
}

isActiveProduct doesn't work because it doesn't know what productCode is. I've tried doing this.productCode, self.productCode, self.mySecondObject().productCode, none of them seem to work. Is it possible to access the value? Is something wrong in my overall VM setup that is causing this to fail?

Thanks

Steve

UPDATE: I'm now not making the objects observable and declaring my VM as so:

var viewModel = function(object1, object2...) {
    var self = this;
    var activeProductCodes = ['AB-1', 'AB-2', 'AB-3'];

    self.myFirstObject = {
        field1: ko.observable(object1.field1),
        field2: ko.observable(object1.field2),
        field3: ko.observable(object1.field3)
    }

    self.mySecondObject = {
        productCode: ko.observable(object2.productCode),

        isActiveProduct: ko.computed(function() {
            return self.activeProductCodes.indexOf(productCode) !== -1 ? true : false;
        }, self)
    }
}

Solution

  • The short discussion in comments aside, when I deal with sub-viewmodels in knockout I tend to define them properly, instead of using anonymous objects. So in your case that might look like this

    var viewModel = function(object1, object2...) {
        var self = this;
        var activeProductCodes = ['AB-1', 'AB-2', 'AB-3'];
    
        self.myFirstObject = ko.observable(new myFirstViewModel(object1)); // omitted for brevity
    
        self.mySecondObject = ko.observable(new mySecondViewModel(object2, activeProductCodes ));
    }
    
    var mySecondViewModel = function(object2, activeProductCodes){
        var self = this;
    
        self.productCode = ko.observable(object2.productCode);
        self.isActiveProduct = ko.computed(function() {
                return activeProductCodes.indexOf(self.productCode()) !== -1 ? true : false;
        }, self)
    }
    

    I also mentioned that theres a good chance you dont need the sub viewmodels to actually be observable, so you might get away with this:

    self.mySecondObject = new mySeocndViewModel(object2, activeProductCodes );
    

    It depends on your use case.