TugboatCaptain
TugboatCaptain

Reputation: 4328

Observable loses value after call to applyBindings

I am working on this fiddle trying to isolate a problem I'm having with the value not being set on a select element and now I'm stuck with nonsensical behavior in jsfiddle. I can't tell if this issue is my underlying problem or if this is a bug in jsfiddle.

First I'm using inheritance with my view models as described here: Using Super Constructors Is Critical In Prototypal Inheritance In Javascript . Perhaps this article has led me down the wrong path, I don't know. Bottom line is that I need to do inheritance.

Second the problem with this particular fiddle is that after the call to ko.applyBindings my observable just loses its value (becomes undefined) and then out of no where gets set to 1.

enter image description here

function userAddressModelBase(data) {
    var self = this;
    self.states = ko.observableArray(data.states);
}

userAddressModel.prototype = new userAddressModelBase({});
userAddressModel.constructor = userAddressModel;

function userAddressModel(data) {
    var self = this;

    userAddressModelBase.call(self, data);

    self.sampleText = ko.observable("i'm here");

    console.log("data.selectedStateId is: " + data.selectedStateId);
    self.selectedStateId = ko.observable(data.selectedStateId);
    console.log("self.selectedStateId is: " + self.selectedStateId());

    self.getStates = function () {
        console.log("getStates running...");
        window.setTimeout(function () {
            console.log("getStates callback...");
            self.states([new stateModel({
                id: 1,
                name: "New York"
            }), new stateModel({
                id: 2,
                name: "Texas"
            }), new stateModel({
                id: 3,
                name: "California"
            }), new stateModel({
                id: 4,
                name: "Ohio"
            })]);
            console.log(ko.toJS(self));
            console.log("getStates callback self.selectedStateId is: " + self.selectedStateId());
        }, 1000);
    };

    //console.log("self.selectedStateId is: " + self.selectedStateId());
    //self.getStates();
    //console.log("self.selectedStateId is: " + self.selectedStateId());
}

function stateModel(data) {
    var self = this;
    self.id = ko.observable(data.id);
    self.name = ko.observable(data.name);
}

var model = new userAddressModel({ selectedStateId: 3 });

console.log(ko.toJS(model));
console.log("before applyBindings model.selectedStateId is: " + model.selectedStateId());
console.log("appling bindings...");
ko.applyBindings(model); // selectedStateId is now undefined!!!
console.log("appling bindings finished.");
console.log(ko.toJS(model));

console.log("after applyBindings model.selectedStateId is: " + model.selectedStateId());
model.getStates(); // selectedStateId is now 1 after this finishes!!!

Upvotes: 2

Views: 617

Answers (1)

Jeff Mercado
Jeff Mercado

Reputation: 134561

What makes you think that your selectedStateId should have a value? Sure you set it initially with one value but when everything has had a chance to load and bind, it doesn't mean it has to keep that value.

That observable is bound to the value of an empty select dropdown. With no values available, what else is supposed to be selected? Only later on do you fill the select with some values so now you have a value.

If you wanted to preserve that value, you need to make sure that it is not empty by the time you apply the bindings or set the value.

Upvotes: 3

Related Questions