Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to order knockout bindings?

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?

like image 670
user1740381 Avatar asked Nov 03 '12 15:11

user1740381


3 Answers

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'] };

like image 68
DrSammyD Avatar answered Oct 12 '22 16:10

DrSammyD


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);
    }
};
like image 25
John Earles Avatar answered Oct 12 '22 16:10

John Earles


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

like image 28
Surya Avatar answered Oct 12 '22 18:10

Surya