Select2 w/ knockout

by mcannon

HTML

<script src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<link rel="stylesheet" href="http://ivaynberg.github.com/select2/bootstrap/css/bootstrap.css">
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.css">
<script src="http://cdnjs.cloudflare.com/ajax/libs/select2/3.5.2/select2.js"></script>
Color Multi
<div>
    <div style="width:200px" data-bind="select2: { data:{ results: values}, placeholder: 'pick some colors', multiple: true, selectedOptions: selected }"></div>
</div>

<hr/>
Color Single
<div>
    <div style="width:200px" data-bind=" value: selectedColorValue, select2: {   data:{ results: values}, allowClear: true, placeholder: 'Select...' }"></div>
</div>

<hr/>
Hair Single
<div>
<div style="width:200px" data-bind=" value: selectedHairValue, 
 select2: {   id: 'code', data:{ results: hairOptions, text: 'description'}, allowClear: true, placeholder: 'Select...' } ">
</div>
</div>

<hr/>
Hair - Multi w/ DIV
<div>
<div style="width:200px" data-bind="selectedOptions:selectedHairValues,select2: { data:{ results: hairOptions,text: 'description'},  placeholder: 'Select...', multiple:true,id:'code',selectedOptions: selectedHairValues} " class="select2 form-control">
</div>
</div>

<hr/>
Rank - Multi w/ select
<div>
<select style="width:200px" multiple="true" data-bind="options: rankOptions, selectedOptions: selectedRankValues, 
optionsText:'description',							  optionsValue:'code', select2: {   placeholder: 'Select...' } " class="select2 form-control">
</select>
</div>
<br/>      
<br/> 
<br/> 
                            <hr/>
<pre data-bind="text: ko.toJSON($root, null, 2)"></pre>

JavaScript

ko.bindingHandlers.select2 = {
    init: function(el, valueAccessor, allBindingsAccessor, viewModel) {
      ko.utils.domNodeDisposal.addDisposeCallback(el, function() {
        $(el).select2('destroy');
      });

      var allBindings = allBindingsAccessor(),
          select2 = ko.utils.unwrapObservable(allBindings.select2);

      $(el).select2(select2);
    },
    update: function (el, valueAccessor, allBindingsAccessor, viewModel) {
        var allBindings = allBindingsAccessor();
console.log("update - ");
        if ("value" in allBindings) {
            $(el).select2("val", allBindings.value());
        } else if ("selectedOptions" in allBindings.select2) {
            var converted = [];
            var textAccessor = function(value) { return value; };
            if ("optionsText" in allBindings) {
                textAccessor = function(value) {
                    var valueAccessor = function (item) { return item; }
                    if ("optionsValue" in allBindings) {
                        valueAccessor = function (item) { return item[allBindings.optionsValue]; }
                    }
                    var items = $.grep(allBindings.options(), function (e) { return valueAccessor(e) == value});
                    if (items.length == 0 || items.length > 1) {
                        return "UNKNOWN";
                    }
                    return items[0][allBindings.optionsText];
                }
            }
            $.each(allBindings.select2.selectedOptions(), function (key, value) {
                converted.push({id: value, text: textAccessor(value)});
            });
            $(el).select2("data", converted);
        }
    }
};

ko.applyBindings({
    values: [
          {id: 1, text: 'red'},
          {id: 2, text: 'blue'},
        {id: 3, text: 'green'},
        {id: 4, text: 'pink'},
        {id: 5, text: 'purple'}
    ],
    selectedColorValue: ko.observable(""),
    selected: ko.observableArray([2]),
    selectedHairValue:...