【问题标题】:How to scroll to selected node in PrimeNG Tree如何滚动到 PrimeNG 树中的选定节点
【发布时间】:2017-05-12 05:53:00
【问题描述】:

我有一个带有 PrimeNG 树和一个自动完成字段的页面。我的要求是当用户在自动完成字段中输入并选择文本时,树应该扩展到匹配节点,并且它应该滚动到匹配节点并突出显示该节点。

我尝试通过将“expanded”属性设置为“true”来扩展树。但我没有找到滚动到选定节点的方法。对此的任何帮助表示赞赏。

如果有任何使用选定节点扩展树的方法,请告诉我。

【问题讨论】:

    标签: angular primeng


    【解决方案1】:

    可能不是最漂亮的解决方案,但是您可以通过使用以下 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 装饰器来获得两者。

    【讨论】:

      【解决方案2】:

      扩展 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();
            }
        }
      

      【讨论】:

      • 嗨,你能详细说明一下你可以在哪里调用这个函数任何特定的钩子吗?
      【解决方案3】:

      添加约翰和大卫的答案。 以下语句将树中的所有节点(包括子节点)作为元素的平面数组返回。

      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'});
           }
        }
      

      }

      希望对你有所帮助。

      【讨论】:

        【解决方案4】:

        这些都有假设。 John's 似乎假设了一个根项目。 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 );
            } ) );
            //
        });
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-01-15
          • 2011-07-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多