KendoUIのツリービューを使用しており、ユーザーがそれをフィルタリングできるようにしたいと考えています。私がやりたいことを実行するデモもあります(http://demos.kendoui.com/web/treeview/api.html)
問題は、フィルターがTreeViewの第1階層にのみ適用されるため、フィルターテキストが子に存在し、親には存在しない場合、子は表示されないことです。
例:
検索テキストが「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);
更新2016-01-13: ユーザー文字列に基づいてTreeViewフィルタリングを実行する方法 を示すヘルプトピックがあります。 。
必要なノードのみが表示されるように、子データソースを手動でフィルタリングする必要があります。レベルごとに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 });
JQueryセレクターを使用して必要な子ノードを表示および非表示にするだけでこれを実現する方法を見つけました。
まず、ツリービューを作成するときに、次のパラメーターをオプションに追加します。
loadOnDemand:false
このようにして、ツリーは要求される前に子ノードのすべての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();
}
});
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();
}
});
まず第一に。 KendoTreeViewは、ASP.NETのTeleriks RadDropDownTreeと比較して非常に低レベルの制御です http://www.telerik.com/help/aspnet-ajax/dropdowntree-overview.html (つまり、もちろんjsを意味します!)これをjquery/kendoに持っていく必要があります...このフィルターを改善する必要があるため、「findByText」ではなくデータアイテムで適切なフィルター処理を行う場合は、次のようにします。
.1)すべてのデータ項目を検索します。2)条件をチェックします(ここでは小文字が値/テキストに含まれます)。
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);
}
});
質問をよく読んだ場合、それはツリービュー自体ではなく、ビュー内のデータのフィルタリングに関するものです。それは再帰によって行うことができます。
動作する再帰の例:
<!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>
このバージョンはツリー全体を検索し、大文字と小文字を区別せず、検索クエリ(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;
};
});