antonio_mg antonio_mg - 4 months ago 39
Ajax Question

Knockout dropdown cascade option not update

I'm trying to populate default value for dependent dropdown using knockout.

When values are harcoded it works, but I need to get values from ajax request and then, the second dropdown option is not updated. The value self.selectedState is updated but I guess that as I haven't already the options populated, then value in select is not bind. This is my code so far:



function myViewModel(country, state) {
var self = this;
self.selectedCountry = ko.observable();
self.selectedState = ko.observable();

self.availableCountries = ko.observableArray([
{
id: 1, name: 'United States', states: [
{ id: 1, name: 'Alabama' },
{ id: 2, name: 'California' },
]
},
{
id: 2, name: 'Canada', states: [
{ id: 53, name: 'Alberta' },
]
}
]);

self.availableStates = ko.observableArray([]);

self.selectedCountry.subscribe(function() {
self.availableStates([]);

for (var i = 0; i < self.availableCountries().length; i++) {
if (self.availableCountries()[i].id == self.selectedCountry()) {
self.availableStates(self.availableCountries()[i].states);
break;
}
}
});

self.selectedCountry(1).selectedState(2);
}

var viewModel = new myViewModel();
ko.applyBindings(viewModel);

<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<select data-bind="options: availableCountries, optionsText: 'name', optionsValue: 'id', optionsCaption: 'Select a country...',
value: selectedCountry"></select>

<select data-bind="options: availableStates, optionsText: 'name',optionsValue: 'id', value: selectedState, visible: availableStates().length > 0" style="display:none"></select>





Is there something special that needs to be done when options are obtained from ajax?

jsfiddle

Answer

The issue isn't AJAX, specifically, but the fact that self.selectedState doesn't have a corresponding option for some time (while the options are being fetched). From the docs:

Normally, when you use the value binding on a <select> element, it means that you want the associated model value to describe which item in the <select> is selected. But what happens if you set the model value to something that has no corresponding entry in the list? The default behavior is for Knockout to overwrite your model value to reset it to whatever is already selected in the dropdown, thereby preventing the model and UI from getting out of sync.

However, sometimes you might not want that behavior. If instead you want Knockout to allow your model observable to take values that have no corresponding entry in the <select>, then specify valueAllowUnset: true. In this case, whenever your model value cannot be represented in the <select>, then the <select> simply has no selected value at that time, which is visually represented by it being blank.

Comments