This does NOT work (custom binding is called but dropdown is empty)
The generic solution
HTML
<select id="parentArea" data-bind="comboBox:{
options: parentAreas,
optionsCaption:'Choose...' ,
optionsText: 'Label',
value: selectedParentArea
}"></select>
and javascript is
ko.bindingHandlers.comboBox = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
var bindings = valueAccessor();
var optionsObservableArray = bindings.options;
optionsObservableArray.subscribe(function (newObservableArray) {
if (newObservableArray && newObservableArray.length > 0) {
if (element.comboBoxInitialised) {
return;
}
ko.applyBindingsToNode(element, {
options: bindings.options,
optionsCaption: bindings.optionsCaption,
optionsText: bindings.optionsText,
value: bindings.value
});
$(element).chosen({});
element.comboBoxInitialised = true;
}
});
}
};
Yup, just reorder your bindings (fiddle: http://jsfiddle.net/gBhbx/4/):
<select id="parentArea" class="chosen-select" data-bind="
options: parentAreas,
optionsCaption: 'Choose...',
optionsText: 'Label',
chosen:{},
value: selectedParentArea">
</select>
Its a antipattern that you depend on the order of bindings.
If you have a custom binding that needs other bindings to run before itself you should call those bindings from the custom binding like
ko.applyBindingsToNode(element, { options: arr, value: val });
and after that do $(element).chosen
I think that your problem is in the chosen
plugin itself. When you apply .chosen
on your select
tag it changes its markup(it's not longer a normal html select
).
So in your bindning your apply chosen
custom binding first which then change the html markup and so your binding are not working properly..
To solve that problem you need to apply your custom binding last not at first .. so that ko binding are applied normally then your custom binding is applied and change your select(but now you have built your select properly)
Update
to run function after the option
elements are generated you can use optionsAfterRender
callback .. Check out the documentaion here
Another dirty solution is to use settimeout