Kendo UI drop downs look great.  Here is a Kendo UI drop down with default styling in closed and open view:

image_34.png

image_35.png

It is built with this HTML:

<input id="kendoDropDown" type="text" />

and this JavaScript:

// Init the drop down
$("#kendoDropDown").kendoDropDownList({
    dataValueField: "id",
    dataTextField: "name",
    dataSource: [
        { id: "1", name: "apple" }, 
        { id: "2", name: "orange" }, 
        { id: "3", name: "banana" }
    ]
});

The snag

Unfortunately, this handsome drop down doesn't integrate smoothly with Knockout JS when it comes to data binding.

We should be able to update our HTML to use a Knockout binding:

<p>
    <label for="kendoDropDown">Kendo UI Drop Down</label>
    <input id="kendoDropDown" type="text" data-bind="value: fruitId"
    />
</p>

Then add a view model and apply the Knockout binding:

// Define and init the Knockout view model
var ViewModel = function () {
        var self = this;
        self.fruitId = ko.observable();
    },
    vm = new ViewModel();   

// Set the initial fruit value
vm.fruitId("2"); // orange

// Wire up KO binding
ko.applyBindings(vm);

We should see a drop down loaded with the view model's initial value of "2" (orange), but the first value in the list ("1" apple) is selected instead.  What's going on?

More investigation

I thought maybe I had a Knockout bug in my code, so I played around with a plain (non-Kendo) select list and a plain text box by adding the following HTML:

<p>
    <label for="select">Plain old select</label>
    <select id="select" data-bind="value: fruitId">
        <option value="1">apple</option>
        <option value="2">orange</option>
        <option value="3">banana</option>
    </select>
</p>
<p>
    <label for="textBox">Plain old text box</label>
    <input id="textBox" type="text" data-bind="value: fruitId" />
</p>

But these controls were set to the correct initial value ("2" orange).

It gets weirder when you change the view model's value programmatically.  Here, I've added some HTML buttons to do that:

<p>
    <button id="changeTo3" class="k-button">change fruitId to "3" (banana) programmatically</button>
</p>
<p>
    <button id="changeTo2" class="k-button">change fruitId to "2" (orange) programmatically</button>
</p>

and some JavaScript to change the view model's values:

// Wire up the buttons
$("#changeTo3").click(function () {
    vm.fruitId("3"); // banana
});
$("#changeTo2").click(function () {
    vm.fruitId("2"); // orange
});

Clicking the buttons should change the view model's value, which should change the controls' values.  It works for the plain HTML controls, but not for the Kendo UI drop down.

Here's the JSFiddle to see all this in action.

<p>The fruitId should be "2" (orange) initially, then "3" (banana) after
    the button click. The text box and the drop down are bound to the same
    value in the Knockout view model (fruitId).</p>
<p>As the drop down is changed manually, the Knockout view model is updated,
    and the drop down and text box show the new value. But as the button is
    clicked and the view model is updated in code, the text box shows the correct
    value, but the drop down does not.</p>
<p>How can the drop down be set in code with Knockout?</p>
<p>
    <label for="kendoDropDown">Kendo UI Drop Down</label>
    <input id="kendoDropDown" type="text" data-bind="value: fruitId"
    />
</p>
<p>
    <label for="select">Plain old select</label>
    <select id="select" data-bind="value: fruitId">
        <option value="1">apple</option>
        <option value="2">orange</option>
        <option value="3">banana</option>
    </select>
</p>
<p>
    <label for="textBox">Plain old text box</label>
    <input id="textBox" type="text" data-bind="value: fruitId" />
</p>
<p>
    <button id="changeTo3" class="k-button">change fruitId to "3" (banana) programmatically</button>
</p>
<p>
    <button id="changeTo2" class="k-button">change fruitId to "2" (orange) programmatically</button>
</p>
// Init the drop down
$("#kendoDropDown").kendoDropDownList({
    dataValueField: "id",
    dataTextField: "name",
    dataSource: [
        { id: "1", name: "apple" }, 
        { id: "2", name: "orange" }, 
        { id: "3", name: "banana" }
    ]
});

// Define and init the Knockout view model
var ViewModel = function () {
        var self = this;
        self.fruitId = ko.observable();
    },
    vm = new ViewModel();   

// Set the initial fruit value
vm.fruitId("2"); // orange

// Wire up KO bindidng
ko.applyBindings(vm);

// Wire up the buttons
$("#changeTo3").click(function () {
    vm.fruitId("3"); // banana
});
$("#changeTo2").click(function () {
    vm.fruitId("2"); // orange
});

The work around

A Kendo UI team blog post describes a work around for this issue, but it didn't work for me.

The trick here is that the Kendo UI drop down is really a hidden input and a bunch of spans.  Knockout changes the value of the hidden input when the view model changes, but you have to hook into that jQuery DOM change event and call the code to select a new value in the Kendo drop down.  Kind of lame, but it's supposed to work.

$("#kendoDropDown").bind("change", function() {
    $(this).data("kendoDropDownList").select(this.selectedIndex);
});

You can even unhide the hidden text box inside the Kendo UI drop down list and watch its value change as the view model changes, but the drop down just sits there.  Arg!

The real work around

I was pulling my hair out by now, and asked for help on Stack Overflow.  Unfortunately, the answer I got was use another library that does the integration in a different way, the Knockout-Kendo.js library.  That's probably a good answer, but I was hoping to avoid adding another library just to use Knockout and Kendo UI together.

Instead, I found I could get everything working as expected with a Knockout subscription.  It's like a view model data change listener.  My thinking was that I could use the same concept as the Kendo UI team blog post (listen for a change and then manually set the drop down).  Not ideal, but oh well.

Here's what I changed in the view model:

self.fruitId.subscribe(function (newValue) {
    $("#kendoDropDown").data("kendoDropDownList").value(newValue);
});

And the final, working JSFiddle.

// Init the drop down
$("#kendoDropDown").kendoDropDownList({
    dataValueField: "id",
    dataTextField: "name",
    dataSource: [
        { id: "1", name: "apple" }, 
        { id: "2", name: "orange" }, 
        { id: "3", name: "banana" }
    ]
});

// Kendo UI team work recommended around
//$("#kendoDropDown").bind("change", function() {
//    $(this).data("kendoDropDownList").select(this.selectedIndex);
//});

// Define and init the Knockout view model
var ViewModel = function () {
        var self = this;
        self.fruitId = ko.observable();
        // Real work around
        self.fruitId.subscribe(function (newValue) {
            $("#kendoDropDown").data("kendoDropDownList").value(newValue);
        });
    };
    vm = new ViewModel();   

// Set the initial fruit value
vm.fruitId("2"); // orange

// Wire up KO binding
ko.applyBindings(vm);

// Wire up the buttons
$("#changeTo3").click(function () {
    vm.fruitId("3"); // banana
});
$("#changeTo2").click(function () {
    vm.fruitId("2"); // orange
});