[英]Filter through nested ul/li structure with input field, reset to original state if input is empty
我有一個 JSON 對象,用於使用列表構建樹視圖。 JSON 對象具有以下結構;
const data = [
{ "name": "Node 1", "children":
[
{ "name": "Node 1.1", "children":
[
{ "name": "Node 1.1.1", "children": [], "leaf": true },
{ "name": "Node 1.1.2", "children": [], "leaf": true }
]
},
{ "name": "Node 1.2", "children":
[ { "name": "Node 1.2.1", "children": [], "leaf": true } ]
}
]
},
{ "name": "Node 2", "children":
[
{ "name": "Node 2.1", "children": [] },
{ "name": "Node 2.2", "children":
[ { "name": "Node 2.2.1", "children": [], "leaf": true } ]
}
]
},
{ "name": "Node 3", "children": [] }
];
然后在createTree
函數中使用該對象;
createTree(nodes, container)
{
const list = document.createElement('ul');
nodes.forEach((node) => {
const listItem = document.createElement('li');
listItem.textContent = node.name;
list.appendChild(listItem);
if (node.children) {
const childList = document.createElement('li');
this.createTree(node.children, childList);
list.appendChild(childList);
}
});
container.appendChild(list);
}
nodes
最初是data
對象, container
是放置樹的元素。該函數構建以下樹視圖;
<ul>
<li>Node 1</li>
<li>
<ul>
<li>Node 1.1</li>
<li>
<ul>
<li>Node 1.1.1</li>
<li>
<ul></ul>
</li>
<li>Node 1.1.2</li>
<li>
<ul></ul>
</li>
</ul>
</li>
<li>Node 1.2</li>
<li>
<ul>
<li>Node 1.2.1</li>
<li>
<ul></ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Node 2</li>
<li>
<ul>
<li>Node 2.1</li>
<li>
<ul></ul>
</li>
<li>Node 2.2</li>
<li>
<ul>
<li>Node 2.2.1</li>
<li>
<ul></ul>
</li>
</ul>
</li>
</ul>
</li>
<li>Node 3</li>
<li>
<ul></ul>
</li>
</ul>
這幾乎是我想要的方式,有很多不必要的li
和ul
標簽,但是因為我使用的是list-style-type: none
這並不重要,不必要的元素被折疊而不顯示。
我還添加了一個輸入字段,用於過濾樹並只顯示相關的葉子(因此是 JSON 對象中的leaf
值)。 它應該只顯示相關的葉子,還有它們的父母。 我已經設法使用以下過濾器功能部分地做到了這一點;
$('#input').on('keyup', () => {
const value = $('#input').val().toLowerCase().trim();
const nodes = oldData.filter(function f(node) {
if (node.name.toLowerCase().includes(value)) return true;
if (node.children) {
return (node.children = node.children.filter(f)).length;
}
});
// Simply removes all children from the root element so there's only one tree, instead of the new tree being stacked on top of the new one
this.removeTree();
// Rebuild the new tree
this.createTree(nodes, document.getElementById('root-element'));
});
這在某種意義上是有效的,它只顯示相關的葉子,包括它們的父節點,但是如果您清空輸入字段,則只有在搜索詞之后可見的元素才會可見。 我知道為什么會發生這種情況( filter
功能會刪除所有不匹配項),但我不知道如何防止這種情況發生。 我嘗試將data
的初始狀態存儲在keyup
事件偵聽器之外的變量中,並在輸入字段為空時將nodes
設置為該變量,但這似乎沒有幫助。
我也試過瀏覽實際的 HTML 樹,但我什至無法正確訪問節點 1、2 和 3 的子節點,所以我在那里也不知所措。
換句話說,過濾樹的葉子同時也顯示它們的父母並在過濾器為空后恢復原始的最佳方法是什么?
使用jQuery.grep()
;
const nodes = $.grep(data, function f(node) {
if (node.name.toLowerCase().includes(value)) return true;
});
據我了解,您有兩個問題。
let oldData = data;
您將獲得指向初始“數據”對象的鏈接,而不是另一個對象。 有很多方法可以復制對象,我通過 JSON 使用。$(document).ready(() => {
createTree(data, $('#container'));
$('#asdf').on('keyup', () => {
let dataCopy = JSON.parse(JSON.stringify(data));
const value = $('#asdf').val().toLowerCase().trim();
let nodes = {};
if (!value) { nodes = data; } else {
nodes = filterData(dataCopy, value);
}
// Simply removes all children from the root element so there's only one tree, instead of the new tree being stacked on top of the new one
this.removeTree();
// Rebuild the new tree
this.createTree(nodes, $('#container'));
});
});
function filterData(data, name) {
return data.filter(function(o) {
if (o.children) o.children = filterData(o.children, name);
return o.name.toLowerCase().includes(name) || o.children.length;
});
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.