How to order knockout bindings?

2019-04-07 09:00发布

I am using knockout.js. I am stuck in a little bit strange situation ( its hard to explain but i am trying, sorry if i am not clear ). I am using custom binding and options binding on a single select-list :

  <select data-bind="options : arrayOfOptions, optionsText: 'Name', 
           optionsValue: 'Name', chosen: { }">
  </select>

ko.bindingHandlers.chosen = {
    init: function (element, valueAccessor, allBindingAccessor, 
                    viewModel, bindigContext) {
        var options = ko.utils.unwrapObservable(valueAccessor() || {});
        $(element).chosen(options);
    }
};

Here at runtime selectlist will fill with all available options from the arrayOfOptions array and chosen is a custom binding in which i am applying a CHOSEN PLUGIN on the select-list.

Now the problem i am facing here is that in custom binding when i applied choose plugin on select list at that time the selectlist is not filled with the options from the arrayOfOptions array. Means in a simple term the custom binding is executing before options binding. Can anybody please give me a solution for this so that custom binding applied after options binding?

4条回答
干净又极端
2楼-- · 2019-04-07 09:40
ko.bindingHandlers.chosen = {
init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
    var options = allBindingsAccessor().options;

    options.subscribe(function (newValue) {
        $(element).chosen();
        $(element).trigger("chosen:updated");
    });

    var value = allBindingsAccessor().value;
    value.subscribe(function (newValue) {
        $(element).trigger("chosen:updated");
    });
},
update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
    if (element.options.length > 0) {
        $(element).chosen();
        $(element).trigger("chosen:updated");
    }
}

};

This Worked for me with KO JS 3.0

查看更多
别忘想泡老子
3楼-- · 2019-04-07 09:44

While the answers above may solve the problem that was presented, they seem to fall short on customizing your chosen drop down menu, such as disabling search by passing {'disable_search':true}.

I suggest the following modifications to allow passing chosen customization in your binding.

<select data-bind="options : arrayOfOptions, optionsText: 'Name', 
    optionsValue: 'Name', chosen: { 'disable_search': true }">
</select>

ko.bindingHandlers.chosen = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var options = allBindingsAccessor().options;
        var chosenOptions = allBindingsAccessor().chosen;

        options.subscribe(function (newValue) {
            $(element).chosen(chosenOptions);
            $(element).trigger("chosen:updated");
        });

        var value = allBindingsAccessor().value;
        value.subscribe(function (newValue) {
            $(element).trigger("chosen:updated");
        });
    },
    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        if (element.options.length > 0) {
            var chosenOptions = allBindingsAccessor().chosen;
            $(element).chosen(chosenOptions);
            $(element).trigger("chosen:updated");
        }
    }
};
查看更多
贪生不怕死
4楼-- · 2019-04-07 09:53

Move your call to chosen into the update.

http://jsfiddle.net/jearles/avSfa/28/

--

ko.bindingHandlers.chosen = {
    init: function(element, valueAccessor, allBindingsAccessor, viewModel) {
        var allBindings = allBindingsAccessor();

        var options = {default: 'Select one...'};
        $.extend(options, allBindings.chosen)

        $(element).attr('data-placeholder', options.default);                
    },
    update: function(element, valueAccessor, allBindingsAccessor, viewModel) {
        $(element).chosen();
    }
};

--

Alternatively, you can use setTimeout to move the call to chosen to the bottom of the execution queue. This will give the Knockout options binding time to do its work before chosen tries to transform it.

ko.bindingHandlers.chosen = {
    init: function (element, valueAccessor, allBindingAccessor, 
                    viewModel, bindingContext) {
        var options = ko.utils.unwrapObservable(valueAccessor() || {});
        setTimeout(function() { $(element).chosen(options); }, 0);
    }
};
查看更多
smile是对你的礼貌
5楼-- · 2019-04-07 09:58

Create an after property with an array of bindingHandler names which this binding depends on.

ko.bindingHandlers.chosen = { init: function (element, valueAccessor, allBindingAccessor, viewModel, bindigContext) { var options = ko.utils.unwrapObservable(valueAccessor() || {}); $(element).chosen(options); }, after:['options'] };

查看更多
登录 后发表回答