Search code examples
drop-down-menufilterkendo-uitransportdatabound

Kendo UI Dropdownlist client-side filter not working if dataBound is used to set selected value


The problem is when using Kendo UI Dropdownlist with the dataBound method to set the selected value at load.

The reason for setting the value in the DataBound method is to ensure the transport has returned with the dropdownlist's dataitems to prevent a race condition failure. This is not demonstrated in the static example below, but my dataset is coming from the transport server side call.

Setting the dropdownlist's option filter: "startswith" works very well for simple client side filtering however a problem arises due to the use of dataBound. Very little documentation on this, but dataBound is called when the dropdownlist is initialized AND when any method takes action against it including filtering.

By placing debuggers in the inspector tool I was able to observe the filter method working, then the dataBound method being hit again and setting it to the initialized value. The effect is that it looks like the filter simply failed.

See the following example. To recreate the problem, try to use the dropdownlist's filter feature, type "Apple" and observe what happens.

$("#dropdownlist").kendoDropDownList({
  dataSource: ["Apples", "Oranges"],
  filter: "startswith",
  dataBound: function(e) {
    $("#dropdownlist").data('kendoDropDownList').value("Oranges");
  }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//kendo.cdn.telerik.com/2016.3.914/js/kendo.all.min.js"></script>
<link href="//kendo.cdn.telerik.com/2016.3.914/styles/kendo.nova.min.css" rel="stylesheet" />
<link href="//kendo.cdn.telerik.com/2016.3.914/styles/kendo.common.min.css" rel="stylesheet" />

<input id="dropdownlist" />

I need a way for the dataBound to only fire on initialization or for the filter to no propagate further thereby avoiding the dataBound call after filtering.


Solution

  • After studying the dropdownlist in the DOM, I found a solution, albeit perhaps a bit hacky, to allow the dataBound initialize and set the value after the transport loads the list and prevents it from hijacking the filter method.

    $("#dropdownlist").kendoDropDownList({
      dataSource: ["Apples", "Oranges"],
      filter: "startswith",
      dataBound: function(e) {
        if (e.sender.filterInput.val() === "") {
          $("#dropdownlist").data('kendoDropDownList').value("Oranges");
        }
      }
    });
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="//kendo.cdn.telerik.com/2016.3.914/js/kendo.all.min.js"></script>
    <link href="//kendo.cdn.telerik.com/2016.3.914/styles/kendo.nova.min.css" rel="stylesheet" />
    <link href="//kendo.cdn.telerik.com/2016.3.914/styles/kendo.common.min.css" rel="stylesheet" />
    
    <input id="dropdownlist" />

    By wrapping the dataBound initialization logic with a condition checking to see if the entered filter value (filterInput) is an empty string which it will be on initialization, it allows any subsequent use of the filter to bypass the dataBound logic.

    Please post any other insights or better solutions you have to this if you have one.