I'm building a simple app with Knockout.js as a proof of concept. As I'm very new to Knockout, the code in this question may be far from perfect and exhibit bad practices, so feel free to let me know if that's the case!
I'm using the options
binding to produce the contents of a select
element:
<select data-bind="options: titles, optionsText: 'display', optionsValue: 'value'">
</select>
The View Model looks like this:
var ViewModel = function() {
this.titles = ko.observableArray([]);
};
On DOM ready I am pushing some values into that observable array (each value is an object literal, representing a "title", e.g. "Mr", "Mrs" etc):
var data = [
{ value: "Mr", display: "Default Value" },
{ value: "Miss", display: "Miss" },
{ value: "Mr", display: "Mr" },
{ value: "Ms", display: "Ms" }
];
ko.applyBindings(view);
for(var i = 0; i < data.length; i++) {
view.titles.push(data[i]); //Push titles into observable array
}
Don't ask why there are two objects with the value "Mr", that's just the way the data I have to deal with comes. I can't change it. However, this is what causes the problem. I would expect the first object to represent the selected option, but that's not the case. The third object represents the option
element that actually ends up as the default selection.
I believe this is due to the fact that the observable array causes the option
elements to be added to the DOM one by one as the loop iterates. Knockout attempts to preserve the selected option by checking it's value. After the first iteration, the selected option
has the value "Mr". After the third iteration there is another option
with the value "Mr" so Knockout thinks that it was the previously selected option and selects it.
Here's a link to a fiddle demonstrating the problem. The "Default Value" option should be selected, but is not. If you click the button to add another option with the same value again, that becomes selected, but, according to the documentation, it should not.
My question is, how can this behaviour be prevented?
Why are you pushing items into array one by one? You could just do:
instead of
This would also fix your problem - the first item would be selected by default. Also, if you are not planning on adding new items to that array, you could use ko.observable instead of ko.observableArray
UPDATE: Knockoutjs doesn't seem to like multiple options with the same value. My code won't work properly if you add value binding to a select tag (it will select third item, not first). However, since knockoutjs allows you to access selected object (via value binding), you can remove optionsValue binding and access value via value binding: jsfiddle.net/ej9Ue/1