KendoUI 过滤器 TreeView
Posted
技术标签:
【中文标题】KendoUI 过滤器 TreeView【英文标题】:KendoUI filter TreeView 【发布时间】:2012-08-31 11:01:46 【问题描述】:我正在使用 KendoUI 的树形视图,并希望让用户能够过滤它。 甚至还有一个演示可以满足我的要求(http://demos.kendoui.com/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 的帮助主题。
您需要手动过滤子数据源,以便只显示必要的节点。对于不同的级别有不同的dataTextField
s 使得它更难掌握,所以这段代码只使用了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的主要内容,如果未能解决你的问题,请参考以下文章