This is a sample data that will be loaded from the server in JSON format and constructed into the below object graph. It consists of an array of "Choice" objects, each with properties like id, name, stages, & currentStageId. The "stages" property in the "Choice" object contains an array of "Stage" objects, each with properties like id, name, & value. Each "Choice" object progresses through stages from "First Stage" to "Fourth Stage," allowing users to select a "Stage" from a dropdown list and save it. The "currentStageId" property stores the id of the stage object the respective "Choice" object is currently in.
Note: Different choices can have different types of stages for simplicity.
For Choice 1, the current saved stage is 4.
var data = [
new Choice({
id: 1,
name: "One",
stages: [
new Stage({
id: 1,
name: "First Stage",
value: 25
}),
new Stage({
id: 2,
name: "Second Stage",
value: 50
}),
new Stage({
id: 3,
name: "Third Stage",
value: 75
}),
new Stage({
id: 4,
name: "Fourth Stage",
value: 100
})],
currentStageId: 4
}),
new Choice({
id: 2,
name: "Two",
stages: [
new Stage({
id: 1,
name: "First Stage",
value: 25
}),
new Stage({
id: 2,
name: "Second Stage",
value: 50
}),
new Stage({
id: 3,
name: "Third Stage",
value: 75
}),
new Stage({
id: 4,
name: "Fourth Stage",
value: 100
})],
currentStageId: 3
}),
new Choice({
id: 3,
name: "Three",
stages: [
new Stage({
id: 1,
name: "First Stage",
value: 25
}),
new Stage({
id: 2,
name: "Second Stage",
value: 50
}),
new Stage({
id: 3,
name: "Third Stage",
value: 75
}),
new Stage({
id: 4,
name: "Fourth Stage",
value: 100
})],
currentStageId: 2
})];
The following are the "Choice" & "Stage" models for holding data and ViewModel for binding:
function ViewModel(data) {
var self = this;
self.choices = ko.observableArray(data);
self.selectedChoice = ko.observable();
}
function Choice(data) {
this.id = data.id;
this.name = data.name;
this.selectedStage = ko.observable(ko.utils.arrayFirst(data.stages, function (item) {
return item.id === data.currentStageId;
}));
this.stages = ko.observableArray(data.stages);
}
function Stage(data) {
this.id = data.id;
this.name = data.name;
this.value = data.value;
}
ko.applyBindings(new ViewModel(data));
Here is my view:
<select data-bind="options: choices, optionsText: 'name', value: selectedChoice"></select>
<select data-bind="options: selectedChoice().stages, optionsText: 'name', value: selectedChoice().selectedStage"></select>
Knockout.js 2x version:
- Pre-selection of saved stage is working.
- Selected stage for choice is updated into underlying observable.
Here is the Working sample with KO 2x in js
Knockout.js 3x version:
- Pre-selection of saved stage is not working.
- Selected stage for choice is not preserved. When choice is changed, the selectedStage is set to the first item in the dropdown list each time the choice is changed.
Here is the Working sample with KO 3x
Finally, the actual question:
- Why does the same code behave differently with two versions of KO? Am I missing something new in KO or is it a bug in KO?
- What code changes should be made to produce the same functionality as in the later version of KO using the latest version of KO? My project is being developed with the latest version of Knockout.js 3.1.0, and I don't want to switch back to an older version for this functionality.
- Which behavior of KO version is correct, 2x or 3x? What is happening internally that causes these discrepancies in behavior?
Thanks in advance.