Reputation: 309
I'm using a <select>
box bound via knockout to a computed value wrapping an ID and an observableArray of options. However, when an item is added to the options array, the selection always changes to the first option. I can't for the life of me understand why.
See example below. click the button to add an option and note that the selection changes. This does not appear to happen if I change the select binding to value: optionId, options: options, optionsValue: 'id', optionsText: 'name'
, but I want to know why it's not working as is.
JSFiddle: http://jsfiddle.net/5m8yud69/2/
HTML:
</select>
<button data-bind="click: click">
Click me
</button>
JavaScript: var options = ko.observableArray();
options.push({ id: 1, name: "one" });
options.push({ id: 2, name: "two" });
options.push({ id: 3, name: "three" });
var optionId = ko.observable(3);
var option = ko.computed({
read: function () {
var id = optionId();
return ko.utils.arrayFirst(options(), function (option) { return option.id === id; });
},
write: function (value) {
optionId(value == null ? null : value.id);
}
});
var model = {
optionId: optionId,
option: option,
options: options,
click: function () {
options.push({ id: 4, name: "four" });
model.options(options);
}
};
ko.applyBindings(model);
Upvotes: 0
Views: 509
Reputation: 33439
Your issue is this line in the click function:
model.options(options);
The previous line already updated the observable array, but then this line attempts to set the observable array to itself. (Since model.options
is an alias for options
, this line is equivalent to options(options)
which is more obviously incorrect).
You end up with an observable array that holds itself. (Observable arrays don't actually stop you from putting things that aren't an array into them) This isn't what you want, and is causing all sorts of weird errors.
Simply remove that line and your code works fine. Working version.
Upvotes: 3