Knockout/Select2: Triggering select2 to update based on an observable option updating
Asked Answered
W

1

3

When upgrading from Knockout.js 2.x to 3.x, I've noticed this not working: I have a screen where I have a <select> depending on an observable array of observables, and I wrap the <select> with a Select2 wrapper.

Now, it used to be that when one of the option observables was updated, the select would update. And that is still the case. But I can't get the Select2 binding to update properly at the same time.

I'm using the binding handlers recommended by the Select2 Github page:

ko.bindingHandlers["select2"] = {
    after: ["options", "value", "selectedOptions"],
    init: function (element, valueAccessor) {
        $(element).select2(ko.unwrap(valueAccessor()));

        ko.utils.domNodeDisposal.addDisposeCallback(element, function() {
            $(element).select2("destroy");
        });
    },
    update: function (element, valueAccessor, allBindingsAccessor) {
        //trying various methods to register interest with dependency checking
        //var allBindings = allBindingsAccessor();
        //if (allBindings.options) { allBindings.options(); }
        //if (allBindings.value) { allBindings.value(); }
        //if (allBindings.selectedOptions) { allBindings.selectedOptions(); }
        $(element).trigger("change");
    }
};
(function () {
    var updateOptions = ko.bindingHandlers["options"]["update"];
    ko.bindingHandlers["options"]["update"] = function (element) {
        var ret = updateOptions.apply(null, arguments);
        var $el = $(element);
        if ($el.data("select2")) { $el.trigger("change"); }
        return ret;
    }
})();
(function () {
    var updateSelectedOptions = ko.bindingHandlers["selectedOptions"]["update"];
    ko.bindingHandlers["selectedOptions"]["update"] = function (element) {
        var ret = updateSelectedOptions.apply(null, arguments);
        var $el = $(element);
        if ($el.data("select2")) { $el.trigger("change"); }
        return ret;
    }
})();

Below is an example. You'll notice that when you change the value of one of the inputs that represent the items in the select, it doesn't update the Select2 to match (but it does update the backing select).

http://jsfiddle.net/mrmills/MfttX/1/

Willettawillette answered 20/5, 2014 at 18:31 Comment(0)
T
4

It seems to work fine when you add the optionsValue: 'choice':

<select data-bind="options: choices, 
                   optionsText: 'choice', 
                   optionsValue: 'choice', 
                   select2: {}"></select>

See fiddle

Tablespoon answered 21/5, 2014 at 11:24 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.