I am trying to make jQuery Chosen and KnockoutJS work at the same time.
The problem is "jQuery Chosen" refuses to update options list even though I've created custom binding for it.
Here is the example - http://jsfiddle.net/5fGAf/
I have two changeable selects - "Country" and "Method". "Method" options list depends on country selected. When I select the country for the first time - everything works perfect. But when I want to change the country - "Method" options list remains the same, even though corresponding knockout computed value is updated.
If I manually run $(".chosen-select").trigger('chosen:updated')
in the browser console - options list updates.
Custom binding code:
ko.bindingHandlers.chosen = {
init: function(element) {
$(element).chosen({disable_search_threshold: 10});
},
update: function(element) {
$(".chosen-select").trigger('chosen:updated');
}
};
It works without jQuery, Prototype. js, or any other JavaScript library, and it is compatible with all popular web browsers, such as Chrome, Firefox, Safari, Internet Explorer and Opera. Knockout provides great documentation, amazing real-time tutorials and many live examples with source code.
KnockoutJS library provides an easy and clean way to handle complex data-driven interfaces. One can create self-updating UIs for Javascript objects. It is pure JavaScript Library and works with any web framework. It's not a replacement of JQuery but can work as a supplement providing smart features.
Knockout. js is a minimalist JavaScript framework for web application development. It is a JavaScript library that allows binding HTML elements against any data model. It is primarily used for creating rich and responsive display as well as editor user interfaces with a clean, underlying data model.
You have two problems:
.chosen-select
so your update
function does not find the select
but anyway you should use $(element)
to access the currently bound elementchosen
binding is not connected to the your observable array your update
won't fire when you change that array.You can solve this "update" problem with explicitly declaring a dependency on the options
binding in your custom binding but a better solution would be to delegate to it:
ko.bindingHandlers.chosen = {
init: function(element) {
ko.bindingHandlers.options.init(element);
$(element).chosen({disable_search_threshold: 10});
},
update: function(element, valueAccessor, allBindings) {
ko.bindingHandlers.options.update(element, valueAccessor, allBindings);
$(element).trigger('chosen:updated');
}
};
And use it where you would normally use the options
binding:
<select id="option1" class="form-control"
data-bind="chosen: payoutOptions,
optionsText: 'optionText',
optionsValue: 'optionValue',
value: activePayoutOption"></select>
Demo JSFiddle.
My solution is this:
ko.bindingHandlers.chosen =
{
init: function (element, valueAccessor, allBindings) {
$(element).chosen(valueAccessor());
// trigger chosen:updated event when the bound value or options changes
$.each('value|selectedOptions|options'.split("|"), function (i, e) {
var bv = allBindings.get(e);
if (ko.isObservable(bv))
bv.subscribe(function () { $(element).trigger('chosen:updated'); });
});
},
update: function (element) {
$(element).trigger('chosen:updated');
}
};
You'd use it like so:
<select data-bind="
options: payoutOptions,
optionsText: 'optionText',
optionsValue: 'optionValue',
value: activePayoutOption,
chosen: { disable_search_threshold: 10, width:'100%' }">
</select>
Note that
{ width:'100%',... }
) are not hardwired in the handlerI used a method that is also compatible with all my existing bindings, so I didn't need to go though a ton of html files removing the options
binding.
ko.bindingHandlers.chosen = {
init: function(element, valueAccessor, allBindings) {
$(element).chosen({ disable_search_threshold: 10});
var valueObservable = allBindings.get('value');
var optionsObservable = allBindings.get('options');
var updateList = function() {
$(element).trigger('chosen:updated');
}
if (valueObservable && typeof(valueObservable.subscribe) == 'function') {
valueObservable.subscribe(updateList);
}
if (optionsObservable && typeof(optionsObservable.subscribe) == 'function') {
optionsObservable.subscribe(updateList);
}
$(element).chosen({ disable_search_threshold: 7, width:'100%' });
}
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With