【问题标题】:KendoUI filter TreeViewKendoUI 过滤器 TreeView
【发布时间】:2012-08-31 11:01:46
【问题描述】:

我正在使用 KendoUI 的树形视图,并希望让用户能够过滤它。 甚至还有一个演示可以满足我的要求(http://demos.kendoui.c​​om/web/treeview/api.html)

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

例子:

  • 项目 1
  • 项目 2
    • 项目 xzy
    • 项目 abc

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

  • 项目 2
    • 项目 abc

有人知道怎么做吗?这是我正在使用的代码:

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

【问题讨论】:

    标签: javascript kendo-ui


    【解决方案1】:

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

    首先,当您创建树视图时,将此参数添加到您的选项中:

    loadOnDemand: 假

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

    这是我正在使用的 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();
            }
        });
    

    【讨论】:

    • +!为了这。我唯一要做的就是扩展 jQuery contains 使其不区分大小写。
    • 这很好,但我有一个下降到 4 个级别的树视图,而这段代码似乎只搜索前两个级别.. 我如何让它搜索整个树?跨度>
    • 这很棒,但我有一个下降到 4 级的树视图,看起来它正在搜索整个树,但没有显示任何内容.. 与找到的元素有关降了4级,父母不见了?我如何让它显示父母?
    【解决方案2】:

    2016-01-13 更新:现在有一个显示how to perform TreeView filtering based on a user string 的帮助主题。

    您需要手动过滤子数据源,以便只显示必要的节点。对于不同的级别有不同的dataTextFields 使得它更难掌握,所以这段代码只使用了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 });
    

    【讨论】:

    • 看起来,它仅在存在与过滤器文本完全匹配的文本的节点(需要调整以处理多个节点具有相同文本时的情况)时才有效。假设一个节点文本是“Item abc”并且如果用户输入“abc”作为过滤器文本,findByText("abc") 返回 null,因为它试图匹配确切的节点文本。如果我的假设是错误的,请纠正我。
    • 确实如此。如果你需要松散匹配节点,你可以像这样使用jQuery contains selector$(".k-in:contains('photo')")
    • 试用过的 jQuery 包含选择器,但问题是它只搜索展开的节点(以 HTML 呈现)并且不会匹配折叠节点的子节点。还有其他选择吗?
    • 递归遍历数据源,搜索项目。
    • 我通过创建一个新字段(在树对象中添加了一个新属性)来解决此问题,将附加文本(将所有子节点的文本与父节点一起附加)添加到该字段并使其属性作为过滤器字段...只是一种解决方法,而不是一个很好的解决方案...
    【解决方案3】:

    对于超过 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();
        }
    });
    

    【讨论】:

    • 感谢您提供此解决方案。唯一的问题是它没有隐藏不匹配的节点,所以我对其进行了一些更改:$("#treeview-standards .k-in").closest("li").hide();,它运行良好。比 Kendo 文档为您提供的解决方案要快得多。
    【解决方案4】:

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

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

    【讨论】:

      【解决方案5】:

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

      【讨论】:

        【解决方案6】:

        如果我很好地阅读了这个问题,它是关于过滤视图中的数据而不是树视图本身。它可以通过递归来完成。

        有效的递归示例:

        <!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>

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2012-02-01
          • 1970-01-01
          • 2015-03-29
          • 2012-12-24
          • 1970-01-01
          • 2011-08-07
          • 2019-09-17
          相关资源
          最近更新 更多