Knockoutjs: refresh bindings after populating select list
So as John Earles said, adding items to the select list doesn't trigger a 'change' event. I have concluded that's actually a Good Thing. From one of the (really good) Knockout tutes:
Bindings catch DOM events and correspondingly update viewmodel properties.
That's the reverse behaviour from what I want! So I've stuck with the callback. At present it just calls applyBindings(). You can see an example in this revision of the original fiddle (callbacks etc omitted for clarity).
Julian Suggate
Updated on June 14, 2022Comments
-
Julian Suggate about 2 years
I feel like this must have been asked before, but I've looked at
- Knockout JS binding initial value of dropdown list
- Knockout does not sync manual set of option's selected attribute
- How to pre-select an option in a dropdown knockout js
and
But those problems weren't quite the one I'm facing.
In my view I receive a viewmodel from an ajax call. In that object is a country ID. In a subsequent ajax call, I retrieve a list of countries (name and ID) and populate a select box from the list.
The select box is bound to the viewmodel's country ID using
<select data-bind="value: CountryId"/>
But when I populate the dropdown, the viewmodel's country is not pre-selected. I have to manually call ko.applyBindings(vm), which is a problem because the data is populated from a jQuery plugin that handles cascaded select boxes. It doesn't have references to the viewmodel (nor do I want to provide it). I could expose a callback, but that's a bit yawn.
I have created a fiddle that illustrates this problem more cleanly. If you click on the Test Select button, you will notice that the dropdown is preselected to Item 0. Uncomment the line in the js panel, and Bob's your uncle.
What am I not getting here? Isn't this a basic knockout feature?
-Jules
-
John Earles over 12 yearsI don't think you are going to be able to do what you are trying to do. The value binding will set up a listener on 'change' for the select, to react when you select a new option. You are just adding options to the select, so Knockout has no way of knowing that it should do anything. Even if it did know, it would reset value to 0, because your options don't specify which row is selected - meaning 0 will be selected.
-
Julian Suggate over 12 yearsI think you may be right. I've gone with the callback mechanism for now, however I'm running into a problem with that. Have updated the question with new info.
-
Julian Suggate over 12 yearsScratch that, I have solved the secondary problem. Will post an answer to this question shortly.
-
Julian Suggate over 12 yearsSo as you said, adding items to the select list doesn't trigger a 'change' event. I have concluded that's actually a Good Thing. From one of the (really good) Knockout tutes: > Bindings catch DOM events and correspondingly update viewmodel properties. That's the reverse behaviour from what I want! So I've stuck with the callback. At present it just calls
applyBindings()
. You can see an example in this revision of the original fiddle (callbacks etc omitted for clarity).
-
Julian Suggate over 12 yearsHmm, interesting. Not sure I like the idea of putting logic into comments though! How would this behave if the select list is populated, and then repopulated with a new set of values?
-
John Earles over 12 yearsYou don't have to use the "containerless" syntax... you could also add the "if" to a container div. If the select list items are changed Knockout will re-evaluate the bindings. I've updated my example to show that syntax, and added a second update and clear buttons. jsfiddle.net/jearles/nw4cH/77
-
Julian Suggate over 12 yearsThat's a nice example, thanks. As you can see though, on the second update the bindings update from DOM -> viewmodel (selected item changes to 5), rather than the other way around. I've gone with the manual approach for now. Thanks for your help getting me to see what's going on. I'd mark your comment to the OP above as an answer, but StackOverflow doesn't have that as an option?