我有一个包含PrimeNG树和自动填充字段的页面。我的要求是,当用户在自动填充字段中输入并选择文本时,树应该扩展到匹配节点,并且它应滚动到匹配节点并突出显示节点。
我尝试通过将'expanded'属性设置为'true'来扩展树。但我找不到滚动到所选节点的方法。对此有任何帮助表示赞赏。
如果有任何使用所选节点扩展树的方法,请告诉我。
答案 0 :(得分:2)
可能不是最漂亮的解决方案,但您可以使用以下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
装饰器来获取这两者。
答案 1 :(得分:1)
扩展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();
}
}
答案 2 :(得分:0)
添加John和David的答案。 以下语句以元素的平面数组形式返回树中的所有节点(包括子节点)。
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'});
}
}
}
希望它能有所帮助。
答案 3 :(得分:0)
这些都有假设。约翰似乎假设了一个根项目。 Vadym 的假设树已完全展开。我使用我的,因为表单最初是加载的。我将所选项目扩展到根数组,并将剩余的嵌套树元素折叠起来。此外,我已经填充了父级。我创建了以下 John 解决方案的静态辅助方法版本:
/*
** Scroll to selected item.
**
** Tree value is obtained via:
** <p-tree #MyTree [value]='data' name='myTree' selectionMode='single' [(selection)]='selected'></p-tree>
** @ViewChild( 'MyTree' ) mtree: Tree;
** elementIdName value is in above example: myTree
** Example:
** _PCOMMON.treeScrollToSelectedItem( mtree, 'myTree' );
*/
public static treeScrollToSelectedItem( tree: Tree, elementIdName: string ): number {
let idx: number = -1;
if ( tree.value !== null && tree.selection !== undefined ) {
idx = 0; // Count levels deep
let items: TreeNode[] = [];
let node: TreeNode = tree.selection;
do {
if( node.parent !== undefined && node.parent !== null ) {
items = node.parent.children; // begin of level
idx++;
} else {
items = tree.value;
}
idx = items.findIndex( k => k.key === node.key ) + idx;
node = node.parent;
}
while ( node !== undefined && node !== null );
if( idx > -1 ) {
document.getElementById( elementIdName ).querySelectorAll( 'p-treenode' )[ idx ].scrollIntoView( );
}
}
return idx;
}
这是测试结构:
import { Component, ElementRef, ViewChild, OnInit } from '@angular/core';
import { TreeNode, SelectItem } from 'primeng/api';
import { TreeModule, Tree } from 'primeng/tree';
import { _PCOMMON } from './pcommon';
//
@Component({
template: `<p-tree #MyTree [value]='treeData' id='myTree' name='myTree' selectionMode='single' [(selection)]='selected'></p-tree>`
})
class TestTreeComponent implements OnInit {
@ViewChild( 'MyTree' ) mtree: Tree;
treeData: TreeNode[];
selected: TreeNode = undefined;
ngOnInit () {
this.treeData = [
{ label: 'One (1)', key: '1', children: [], parent: undefined, expanded: false },
{ label: 'Two (2)', key: '2', children: [], parent: undefined, expanded: false },
{ label: 'Three (3)', key: '3', children: [], parent: undefined, expanded: true },
{ label: 'Four (4)', key: '4', children: [], parent: undefined, expanded: false }
];
const children: TreeNode[] = [
{ label: 'Five (5)', key: '5', children: [], parent: this.treeData[2], expanded: false },
{ label: 'Six (6)', key: '6', children: [], parent: this.treeData[2], expanded: false },
{ label: 'Seven (7)', key: '7', children: [], parent: this.treeData[2], expanded: true }
];
const children2: TreeNode[] = [
{ label: 'Eight (8)', key: '8', children: [], parent: children[2], expanded: false },
{ label: 'Nine (9)', key: '9', children: [], parent: children[2], expanded: false }
];
this.treeData[2].children = children;
this.treeData[2].children[2].children = children2;
}
//
}
//
import { TestBed, waitForAsync, ComponentFixture, inject, fakeAsync, tick } from '@angular/core/testing';
//
fdescribe('_PCOMMON_TreeComponent', () => {
/*
** The treeData is as follows:
** One (1)
** Two (2)
** Three (3)
** Five (5)
** Six (6)
** Seven (7)
** Eight (8)
** Nine (9)
** Four (4)
*/
let sut: TestTreeComponent;
let fixture: ComponentFixture<TestTreeComponent>;
//
beforeEach(() => {
TestBed.configureTestingModule({
imports: [ TreeModule ],
declarations: [ Tree, TestTreeComponent ]
});
//
fixture = TestBed.createComponent( TestTreeComponent );
sut = fixture.componentInstance;
//
fixture.detectChanges( ); // trigger initial data binding
fixture.whenStable( );
});
/*
** public static treeScrollToSelectedItem( tree: Tree, elementIdName: string ): number
*/
it( 'treeScrollToSelectedItem, nested selected ...', fakeAsync( ( ) => {
// given
sut.selected = sut.treeData[2].children[2].children[1];
tick( 100 );
fixture.detectChanges( ); // trigger initial data binding
fixture.whenStable( );
console.warn( sut.mtree.selection );
// when
const ret: number = _PCOMMON.treeScrollToSelectedItem( sut.mtree, 'myTree' );
// then
expect( ret ).toEqual( 7 );
} ) );
//
it( 'treeScrollToSelectedItem, first nested selected ...', fakeAsync( ( ) => {
// given
sut.selected = sut.treeData[2].children[0];
tick( 100 );
fixture.detectChanges( ); // trigger initial data binding
fixture.whenStable( );
// when
const ret: number = _PCOMMON.treeScrollToSelectedItem( sut.mtree, 'myTree' );
// then
console.warn( ret );
expect( ret ).toEqual( 3 );
} ) );
//
it( 'treeScrollToSelectedItem, root item ...', fakeAsync( ( ) => {
// given
sut.selected = sut.treeData[2];
tick( 100 );
fixture.detectChanges( ); // trigger initial data binding
fixture.whenStable( );
// when
const ret: number = _PCOMMON.treeScrollToSelectedItem( sut.mtree, 'myTree' );
// then
expect( ret ).toEqual( 2 );
} ) );
//
});