Nockout.js update of picklist doesn't fire on first change

I have 2 picklists and I want to sync the index, so when the first one has index 1, the second one will have index 1, etc.

This is my html.

<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.0/knockout-min.js"></script>

<div>
<select id="selLight" data-bind="options: $root.ddlLight, value: ddlLightSelected"></select>
<select id="selAction" data-bind="options: $root.ddlAction, value: ddlActionSelected"></select>
</div>

      

and javascript ...

var ViewModel = function() {
    var self = this;

    self.ddlLight  = ko.observableArray(["RED", "AMBER", "GREEN"]);
    self.ddlAction = ko.observableArray(["STOP", "READY", "GO"]);
    self.ddlLightSelected  = ko.observable();
    self.ddlActionSelected = ko.observable();

    self.ddlLightSelected.subscribe(function (event) {
        document.getElementById("selAction").selectedIndex =
            self.ddlLight.indexOf(self.ddlLightSelected());
     });

    self.ddlActionSelected.subscribe(function (event) {
        document.getElementById("selLight").selectedIndex =
            self.ddlAction.indexOf(self.ddlActionSelected());
     });    
};

ko.applyBindings(new ViewModel()); 

      

I have a fiddle with the exact problem ...

http://jsfiddle.net/phykell/2vUTw/

EDIT: I had a couple of issues with the jsfiddle, so here's the jsbin ... http://jsbin.com/ilomer/4/

... and here's how to recreate the problem:

  • Run jsFiddle
  • Select GREEN from LIGHTS (ACTIONS will change to GO). 3. Select STOP from ACTIONS (LIGHTS should change to RED, but they won't)
+3


source to share


1 answer


The problem is with this line of code:

document.getElementById("selAction").selectedIndex = self.ddlLight.indexOf(self.ddlLightSelected());

      

You are changing the DOM directly, preventing Knockout from starting the observable pattern.



If you want to change something, always change ko.observable

, not the JavaScript or DOM variable. The knockout recognizes the change and therefore changes the DOM itself. Decision:

self.ddlLightSelected.subscribe(function (event) {
      var index = self.ddlLight.indexOf(self.ddlLightSelected());
      self.ddlActionSelected(self.ddlAction()[index]); // Update the Observable, not the DOM
});

self.ddlActionSelected.subscribe(function (event) {
    var index = self.ddlAction.indexOf(self.ddlActionSelected());
    self.ddlLightSelected(self.ddlLight()[index]); // Update the Observable, not the DOM
}); 

      

Updated JS Bin .

+4


source







All Articles