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
});
+4
source to share