Knockout Binding for KendoUI DropDownBox

Knockout Binding for KendoUI DropDownBox

by toddanglin

HTML

<link rel="stylesheet" href="http://cdn.kendostatic.com/2011.3.1129/styles/kendo.default.min.css">
<link rel="stylesheet" href="http://cdn.kendostatic.com/2011.3.1129/styles/kendo.common.min.css">
<script src="http://cdn.kendostatic.com/2011.3.1129/js/kendo.all.min.js"></script>
<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/jquery.tmpl.js"></script>
<script src="https://raw.github.com/SteveSanderson/knockout/v2.0.0rc2/build/output/knockout-latest.js"></script>
<div id="example">
    <script type="text/x-kendo-template" id="template">
        #= data.name # (#= kendo.toString(data.price,"c") #)
    </script>
 <select data-bind="options: myCars, 
                    value: selectedCar, 
                    optionsText: 'name', 
                    optionsValue: 'id', 
                    optionsCaption: 'Choose one...',
                    kendoDropDownList:{template: kendo.template($('#template').html())}">
    </select>
    
    <input data-bind="dropDownOptions: myCars, 
                    value: selectedCar, 
                    optionsText: 'name', 
                    optionsValue: 'id', 
                    optionsCaption: 'Choose one...',
    kendoDropDownList:{}" />
    
    <select data-bind="options: myCars, 
                    value: selectedCar, 
                    optionsText: 'name', 
                    optionsValue: 'id', 
                    optionsCaption: 'Choose one...'">
    </select>

 <hr/>

 <div data-bind="text: currentCar"></div>      

 <button data-bind="click: addItem">Add Item</button>
 <button data-bind="click: resetDefault">Reset Default</button>
 <button data-bind="click: changeTruck">Change Nested Observable</button>
    
 <div data-bind="text: ko.toJSON(myCars)"></div>
</div>

JavaScript

ko.bindingHandlers.kendoDropDownList = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var unwrap = ko.utils.unwrapObservable,
                binding = allBindingsAccessor(),
                options = (element.nodeName == "SELECT") ? binding.options : binding.dropDownOptions,
                valueProp = unwrap(binding.optionsValue),
                labelProp = unwrap(binding.optionsText) || valueProp,
                caption = binding.optionsCaption,
                currentValue = binding.value,   
                mappedSource = null,           
                config = {};

            if (binding.kendoDropDownList) {
                $.extend(config, binding.kendoDropDownList);
            }
            
            //Set basic DropDownList options (from KO bindings)
            if(config.dataValueField === undefined)
                config.dataValueField = valueProp;
        
            if(config.dataTextField === undefined)
                config.dataTextField = labelProp;
            
            if(config.optionLabel === undefined)
                config.optionLabel = caption;                              

            //Create dependentObservable to handle nested observable objects
            mappedSource = ko.dependentObservable(function(){ return ko.toJS(options); }, viewModel);
            
            //Subscribe to the knockout observable array to get new/remove items
            mappedSource.subscribe(function (newOptions) {
                var ddl = $(element).data('kendoDropDownList'),
                    oldVal = ddl.value();
                
                ddl.dataSource.data(newOptions);
                
                //Reset selected value
                ddl.value(oldVal);
            });

            config.dataSource = new kendo.data.DataSource({ data: mappedSource() });
            
            $(element).kendoDropDownList(config);
        },
        update: function (element,...