KendoUI filter TreeView

烂漫一生 提交于 2019-11-30 06:44:17

Update 2016-01-13: There is now a help topic that shows how to perform TreeView filtering based on a user string.

You need to manually filter the child DataSources, so that only the necessary nodes are shown. Having different dataTextFields for the different levels makes it harder to grasp, so this code uses the text field only. Also, as this filtering is performed on the client-side, it assumes that you have loaded all nodes.

var treeview = $("#treeview").data("kendoTreeView"),
    item = treeview.findByText("Item 1.3"), // find the node that will be shown
    dataItem = treeview.dataItem(item),
    nodeText = dataItem.text;

// loop through the parents of the given node, filtering them to only one item
while (dataItem.parentNode()) {
    dataItem = dataItem.parentNode();
    dataItem.children.filter({ field: "text", operator: "contains", value: nodeText });
    nodeText = dataItem.text;
}

treeview.dataSource.filter({ field: "text", operator: "contains", value: nodeText });

I found a way to make this happen just using jQuery selectors to hide and show the necessary child nodes.

First thing is when you are creating your tree view, add this parameter to your options:

loadOnDemand: false

This way the tree will render out all the HTML of your child nodes before being requested, thereby allowing you to use jQuery to navigate through.

Here is the jQuery code I have working that filters the nodes out that don't match, opens the group of nodes that do match, and shows them.

$("#searchTextInputField").keyup(function () {

        var filterText = $("#searchTextInputField").val();

        if(filterText !== "") {   
            $("#myTree .k-group .k-group .k-in").closest("li").hide();
            $("#myTree .k-group .k-group .k-in:contains(" + filterText + ")").each(function() {
                $(this).closest("ul").show();
                $(this).closest("li").show();
            });
        } else {
            $("#myTree .k-group").find("ul").hide();
            $("#myTree .k-group").find("li").show();
        }
    });

For more than 4 levels traverse all parents of type UL and LI and call show().

$("#filterText").keyup(function (e) {
    var filterText = $(this).val();

    if (filterText !== "") {
        $("#treeview-standards .k-group .k-group .k-in").closest("li").hide();
        $("#treeview-standards .k-group .k-group .k-in:contains(" + filterText + ")").each(function () {
            $(this).parents("ul, li").each(function () {
                $(this).show();
            });
        });
    } else {
        $("#treeview-standards .k-group").find("ul").hide();
        $("#treeview-standards .k-group").find("li").show();
    }
});

First of all. KendoTreeView is very low-level control compared to Teleriks RadDropDownTree from ASP.NET http://www.telerik.com/help/aspnet-ajax/dropdowntree-overview.html (i mean the js of course!) The should have taken this to jquery/kendo... it needed to improve this filter, so if you prefer proper filtering on dataitem instead of "findByText", this does:

.1) finds all dataitems .2) checks your conditions (here lowercase contains on value/text) .3) flag item, flag parents .4) clean up, remove nodes left in tree by parent

that.nodeFilter = { logic: "or", filters: [] };
that.nodeFilter.filters.push({ field: "hidden", operator: "eq", value: false });
tree.element.find(".k-in").each(function () {
    var dItem = tree.dataItem($(this).closest("li"));
    dItem.hidden = false;
    if (dItem[that.options.dataValueField].toLowerCase().indexOf(searchTerm) != -1 ||
        dItem[that.options.dataTextField].toLowerCase().indexOf(searchTerm) != -1) {
        that.nodeFilter.filters.push({ field: that.options.dataValueField, operator: "eq", value: dItem[that.options.dataValueField] })
        while (dItem.parentNode()) {
            dItem = dItem.parentNode();
            dItem.hidden = false;
            that.nodeFilter.filters.push({ field: that.options.dataValueField, operator: "eq", value: dItem[that.options.dataValueField] })
        }
    } else {
        dItem.hidden = true;
    }
});
tree.dataSource.filter(that.nodeFilter);
tree.element.find(".k-in").each(function () {
    var node = $(this).closest("li");
    var dataItem = tree.dataItem(node);
    if (dataItem.hidden) {
        tree.remove(node);
    }
});

This version searches the whole tree, is case insensitive, and hides nodes that do not contain the search query (jQuery 1.8+).

$("#search").keyup(function (e) {
        var query = $(this).val();

        if (query !== "") {
            $("#tree-view .k-in").closest("li").hide();
            $("#tree-view .k-item .k-in:Contains(" + query + ")").each(function () {
                $(this).parents("ul, li").each(function () {
                    $(this).show();
                });
            });
        } else {
            $("#tree-view .k-group").find("ul").hide();
            $("#tree-view .k-group").find("li").show();
        }
    });

jQuery.expr[":"].Contains = jQuery.expr.createPseudo(function (arg) {
    return function (elem) {
        return jQuery(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
    };
});

If I read the question well, it is about filtering the data in the view and not the treeview itself. It could be done by recursion.

Recursion example that works:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>Kendo UI Snippet</title>

    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.117/styles/kendo.common.min.css"/>
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.117/styles/kendo.rtl.min.css"/>
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.117/styles/kendo.silver.min.css"/>
    <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.117/styles/kendo.mobile.all.min.css"/>

    <script src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
    <script src="https://kendo.cdn.telerik.com/2018.1.117/js/kendo.all.min.js"></script>
</head>
<body>
  <div class="demo-section k-content">
    <div id="treeview1"></div>
    <div id="showit"></div>
    <div id="treeview2"></div>
  </div>
<script>
    //
    // Define hierarchical data source
    //
    var mydata = new kendo.data.HierarchicalDataSource({ 
      name: "Food", items: [
      { name: "Meat", items:
        [
          { name: "Pork" },
          { name: "Beef" }
        ]
      },
      { name: "Vegetables", items:
        [
          { name: "Pepper" }          
        ]
      }
      ]
    });

    //
    // When debugging
    //    
    var debug=false;
  
    //
    // Find and return Item when found.
    //
    function FindByName(items, myName)
    {
      //Query definition
      var query = kendo.data.Query.process(items, {
              filter: {
                logic: "or",
                filters: [{
                  field: "name",
                  value: myName,
                  operator: "eq"
                }]
              }
            });
      
       if (debug) $("#showit").html($("#showit").html()+"  found:" + JSON.stringify(query.data));
      
       //
       // return Item when found.
       //
       if (query.data != "")       
         return query.data; //ready
       else
       {
         //
         // if sub-items, search further
         //
         for (let i=0; i<items.length; i++)            
         {
           if (debug) $("#showit").html($("#showit").html()+"  test:" + JSON.stringify(items[i]));
           if (items[i].items!=null)
           {           
             if (debug) $("#showit").html($("#showit").html()+"  search sub....");
             var r = FindByName(items[i].items, myName);
             if (r!=null) return r; //ready, else continue searching further
           };
         }
       }
      if (debug) $("#showit").html($("#showit").html()+"  not found.");
      return null; //nothing found.
    }
  
    //
    // print the input
    //
    $("#showit").html($("#showit").html()+"  Food:" + JSON.stringify(mydata.options.items));
    //
    // print the result
    //
  	var ret=FindByName(mydata.options.items,"Beef");
    $("#showit").html($("#showit").html()+"<p>  Beef:" + JSON.stringify(ret));
    
    $("#treeview1").kendoTreeView({
      dataSource: mydata.options.items,
      dataTextField: ["name"]
    });

    ret=FindByName(mydata.options.items,"Meat");
    $("#showit").html($("#showit").html()+"<p>  Meat:" + JSON.stringify(ret));
    ret=FindByName(mydata.options.items,"Pepper");
    $("#showit").html($("#showit").html()+"<p>  Pepper:" + JSON.stringify(ret));
    ret=FindByName(mydata.options.items,"Vegetables");
    $("#showit").html($("#showit").html()+"<p>  Vegetables:" + JSON.stringify(ret));
    //
    // Example: bind return value [ret] to treeview.
    //
    $("#treeview2").kendoTreeView({
      dataSource: ret,
      dataTextField: ["name"]
    });
</script>
</body>
</html>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!