javascript KendoUI 过滤器 TreeView

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/12303235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 15:52:19  来源:igfitidea点击:

KendoUI filter TreeView

javascriptkendo-ui

提问by Preli

I am using the treeview of KendoUI and want to give the user the possibility to filter it. There is even a demo that does what I want (http://demos.kendoui.com/web/treeview/api.html)

我正在使用 KendoUI 的树视图,并希望让用户可以对其进行过滤。甚至有一个演示可以做我想要的(http://demos.kendoui.c​​om/web/treeview/api.html)

The Problem is that the filter is only applied to the 1st hierarchy of the TreeView, so if the filter-text is present in a child but not the parent, then the child won't be displayed.

问题是过滤器仅应用于 TreeView 的第一个层次结构,因此如果过滤器文本存在于子级而不是父级中,则不会显示子级。

Example:

例子:

  • Item 1
  • Item 2
    • Item xzy
    • Item abc
  • 第 1 项
  • 第 2 项
    • 项目 xzy
    • 项目 abc

If the search text would be "abc", no item would be displayed. Instead I would like to have the following result:

如果搜索文本是“abc”,则不会显示任何项目。相反,我希望得到以下结果:

  • Item 2
    • Item abc
  • 第 2 项
    • 项目 abc

Does anyone know how to do this? This is the code I am using:

有谁知道如何做到这一点?这是我正在使用的代码:

   var tree_view_data = new kendo.data.HierarchicalDataSource({
        transport: {
            read: {
                url: "getall/items",
                dataType: "json"
            }
        },
        schema: {
            model: {
                children: "ChildItems"
            }
        }
    });
    //init tree view itself
    var $treeview = $("#div-treeview").kendoTreeView({
        dataSource: tree_view_data,
        dataTextField: [ "Text", "ChildrenText" ]
    });

    //allow filter of navigation tree
    var refreshTree = function () {
        tree_view_data.filter({
            field: "Text", //if I would use "ChildrenText" here nothing be displayed at all if filtertext is set
            operator: "contains",
            value: $("#tree-text-search").val()
        });
    };

    $("#tree-text-search").change(refreshTree).keyup(refreshTree);

采纳答案by Alex Gyoshev

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

2016 年 1 月 13 日更新:现在有一个帮助主题显示如何根据用户字符串执行 TreeView 过滤

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 textfield only. Also, as this filtering is performed on the client-side, it assumes that you have loaded all nodes.

您需要手动过滤子数据源,以便仅显示必要的节点。具有不同dataTextField的不同的级;使得它更难把握,所以此代码使用text唯一领域。此外,由于此过滤是在客户端执行的,因此假定您已加载所有节点。

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 });

回答by Mike Woj

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

我找到了一种方法来实现这一点,只需使用 jQuery 选择器来隐藏和显示必要的子节点。

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.

这样,树将在被请求之前呈现出您子节点的所有 HTML,从而允许您使用 jQuery 进行导航。

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.

这是我正在使用的 jQuery 代码,它过滤掉不匹配的节点,打开匹配的节点组,并显示它们。

$("#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();
        }
    });

回答by user2620454

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

对于超过 4 个级别,遍历 UL 和 LI 类型的所有父级并调用 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();
    }
});

回答by csharpnoob

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:

首先。与来自 ASP.NET http://www.telerik.com/help/aspnet-ajax/dropdowntree-overview.html 的Teleriks RadDropDownTree 相比,KendoTreeView 是非常低级的控制(我当然是指 js!)应该采取这个到 jquery/kendo ......它需要改进这个过滤器,所以如果你更喜欢对数据项而不是“findByText”进行适当的过滤,这样做:

.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

.1) 查找所有数据项 .2) 检查您的条件(这里小写包含值/文本) .3) 标记项,标记父项 .4) 清理,删除父项留在树中的节点

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);
    }
});

回答by Sunden

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

此版本搜索整个树,不区分大小写,并隐藏不包含搜索查询的节点 (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;
    };
});

回答by David

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>