我有一个包含PrimeNG树和自动填充字段的页面。我的要求是当用户在自动完成字段中输入并选择文本时,应将树扩展到匹配节点,并且它应滚动到匹配节点并突出显示该节点。
我试图通过将'expanded'属性设置为'true'来扩展树。但我找不到滚动到所选节点的方法。对此有任何帮助表示赞赏。
如果有任何方法使用所选节点扩展树,请告诉我。
可能不是最漂亮的解决方案,但您可以通过使用以下util方法实现此目的。
public scrollToSelectionPrimeNgDataTable(table: DataTable, element: HTMLElement) {
if (table.selection !== null && table.value !== null) {
let index = table.value.indexOf(table.selection);
let list = document.querySelectorAll('tr');
if (list !== null && index < list.length) {
let targetElement = list.item(index);
targetElement.scrollIntoView()
}
}
}
要使用此方法,您必须将DataTable的引用和表本身作为HTMLElement传递给方法。你可以通过使用Angular2的@ViewChild
装饰器来获得两者。
扩展David Asher的答案,这是PrimeNG树的一个更简单的工作解决方案:
HTML:
<p-tree #mytreeid id="mytree"></p-tree>
角度:
@ViewChild("mytree") mytree: Tree;
// selection is the TreeNode you want to scroll into view
scrollToSelectionPrimeNgDataTree(selection, tree, elementIdName) {
if (tree.value !== null) {
let index = tree.value.indexOf(selection);
document.getElementById(elementIdName).querySelectorAll("p-treenode")[index].scrollIntoView();
}
}
加上约翰和大卫的答案。以下语句将树中的所有节点(包括子节点)作为平面元素数组返回。
document.getElementById(elementIdName).querySelectorAll("p-treenode")
因此,应正确计算搜索节点的索引。这取决于节点是否扩展。应以深度优先(预订)方式遍历节点树以查找节点的索引。它可以使用递归来实现:
private CalculateIndex(tree: TreeNode[], predicate: (node: TreeNode) => boolean,
startIndex: number = 0 ): { found: boolean; index: number }
{
let index: number = startIndex;
let found = false;
for (const node of tree) {
found = predicate(node);
if (found) {
break;
}
index++;
if (node.expanded) {
({ found, index } = this.CalculateIndex(node.children, predicate, index));
if (found) {
break;
}
}
}
return { found, index };
}
找到索引然后可以在以下函数中使用滚动到节点:
private scrollToSelection(selection: TreeNode, treeNodes: TreeNode[], treeElementId: string) {
const { found, index } = this.CalculateIndex(treeNodes, (node: TreeNode) => node === selection);
if (found) {
const treeElement = document.getElementById(treeElementId);
const allTreeNodes = treeElement.querySelectorAll('p-treenode');
const node = allTreeNodes[index];
if (node) {
node.scrollIntoView({behavior: 'smooth', block: 'center', inline: 'center'});
}
}
}
希望它有所帮助。