KendoUI 过滤器 TreeView

Posted

技术标签:

【中文标题】KendoUI 过滤器 TreeView【英文标题】:KendoUI filter 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);

【问题讨论】:

【参考方案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>

【讨论】:

以上是关于KendoUI 过滤器 TreeView的主要内容,如果未能解决你的问题,请参考以下文章

KendoUI 网格过滤器日期格式

如何使用布尔过滤器设置 KendoUi Grid 样式

应用 TreeView 过滤器后 DataGridView 中出现多余的行

KendoUI TreeView 动态 JSON

qt treeview过滤

kendoui treeview grid spreadsheet