Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout JS and Chosen multiselect not working

I'm using knockout js and the chosen plugin (https://github.com/harvesthq/chosen) to try and make a good looking multi select.

I've tried various ways but can't get the multiselect to work with the data I'm using. When I click on the multiselect, no values are shown even though the options binding contains the correct data.

HTML:

<select multiple="multiple" data-bind="options: allCustomers, 
selectedOptions: event().customers, optionsText: 'name', 
optionsValue: 'id', chosen: true " ></select>​

Simplified version of the view model:

    function Event()
    {
        this.customers = ko.observableArray();
    };                     

    //for chosen plugin
    ko.bindingHandlers.chosen = {
        update: function(element, valueAccessor, allBindingsAccessor, viewModel)  {
            $(element).chosen();
        }
    }

    function ViewModel()
    {   
        this.event = ko.observable(new Event());
        this.allCustomers = ko.observableArray();
    };

    var viewModel = new ViewModel();

    $.getJSON("/get_json", function(data) 
    {                                  
        for (var c = 0; c < data.customers.length; c++)
        {
            viewModel.allCustomers.push(data.customers[c]);
        }   
    });

    ko.applyBindings(viewModel);   

PHP:

function get_json()
{
    $eventData = array(
        'customers' => array(array('name' => 'Bob', 'id' => 1), array('name' => 'John', 'id' => 2)),
        'moreData' => array(),
        'evenMoreData' => array()
        );

    echo json_encode($eventData);
}

This shows the chosen styled select box but when I click in it, no options appear.

When I create a local JS array in the view model for the customers and pass that into allCustomers, the multiselect works correctly (see my jsfiddle) so it's something to do with getting data from the server, but I've been staring at this a while and can't see the problem!

Any help much appreciated

like image 734
peacemaker Avatar asked Jul 06 '12 20:07

peacemaker


2 Answers

I found the problem after @Tyrsius suggested it might not be updating the data after the initial binding.

I added $(element).trigger("liszt:updated"); to the custom binding like so:

ko.bindingHandlers.chosen = {
    update: function(element, valueAccessor, allBindingsAccessor, viewModel)  {
        $(element).chosen();
        $(element).trigger("liszt:updated");
    }
}
like image 79
peacemaker Avatar answered Oct 02 '22 19:10

peacemaker


The code in the accepted version for some reason did not work for me. Probably because the liszt:updated command does not trigger chosen to be updated. Based on docs here I wrote my own version:

ko.bindingHandlers.chosen = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        $(element).chosen({ width: "95%", placeholder_text_multiple: "Select..." });
        var value = ko.unwrap(valueAccessor());
    },

    update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var value = ko.unwrap(valueAccessor());
        $(element).trigger("chosen:updated");

    }
}
like image 39
kubal5003 Avatar answered Oct 02 '22 20:10

kubal5003