This does NOT work (custom binding is called but dropdown is empty)
<select id="parentArea" class="chosen-select" data-bind="
chosen:{},
options: parentAreas,
optionsCaption: 'Choose...',
optionsText: 'Label',
value: selectedParentArea">
</select>
But this works (dropdown is filled)
<select id="parentArea" class="chosen-select" data-bind="
options: parentAreas,
optionsCaption: 'Choose...',
optionsText: 'Label',
value: selectedParentArea">
</select>
I would like to add a custom binding to the dropdown but not sure how to do it.
Custom binding is simple
ko.bindingHandlers.chosen = {
init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
console.log('chosen', element);
$(element).chosen({});
}
};
UPDATE
.chosen({});
is a method from another piece of Javascript (harvesthq.github.io/chosen).
I realised that when it is commented out, the remaining binding work. What I really need is to run "$(element).chosen ({});" AFTER all other binding finish.
UPDATE 2
When I apply 'chosen' manually after all the bindings are applied, it works well. Eg I can use a button which runs this JS
function run() {
$('.chosen-select').chosen({});
};
I just need to do it automatically (a callback function?) when all bindings are complete. I do not know how to do it.
UPDATE 3
"parentAreas" is not a static array. It is loaded from a web service:
function ViewModel() {
var self = this;
self.init = function () {
//load parent areas from web service
};
self.init(); //Running the init code
}
ko.applyBindings( new ViewModel());
I want to initialise "chosen" box custom binding when parent areas are ready.
UPDATE 4
New version (works but is non-reusable since it has hardcoded bindings)
ko.bindingHandlers.chosen = { init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
viewModel.parentAreas.subscribe(function(newParentAreas) {
if (newParentAreas && newParentAreas.length > 0) {
ko.applyBindingsToNode(element, {
options: viewModel.parentAreas,
optionsCaption: 'Choose...',
optionsText: 'Label',
value: viewModel.selectedParentArea
});
$(element).chosen({});
}
});
}
};
// and binding is just data-bind="chosen:{}
UPDATE 5 Avoiding multiple initialisation (hacky way)
ko.bindingHandlers.parentAreaComboBox = {
initialised: false,
init: function (element, valueAccessor, allBindingsAccessor, viewModel, context) {
viewModel.parentAreas.subscribe(function (newParentAreas) {
if (newParentAreas && newParentAreas.length > 0) {
if (ko.bindingHandlers.parentAreaComboBox.initialised) {
return;
}
ko.applyBindingsToNode(element, {
options: viewModel.parentAreas,
optionsCaption: 'Choose...',
optionsText: 'Label',
value: viewModel.selectedParentArea
});
$(element).chosen({});
ko.bindingHandlers.parentAreaComboBox.initialised = true;
}
});
}
};
UPDATE 6
I've written generic solution (see my answer below)