From c1f8afcd607660051c79b3edec0c60a8a73b6d1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Rouzi=C3=A8s?= Date: Fri, 15 Sep 2023 12:18:52 +0200 Subject: [PATCH 1/8] Add virtual scroll inputs to tree select --- src/app/components/treeselect/treeselect.ts | 26 ++++- .../doc/treeselect/treeselectdoc.module.ts | 3 +- .../doc/treeselect/virtualscrolldoc.ts | 110 ++++++++++++++++++ .../pages/treeselect/treeselectdemo.ts | 6 + 4 files changed, 143 insertions(+), 2 deletions(-) create mode 100644 src/app/showcase/doc/treeselect/virtualscrolldoc.ts diff --git a/src/app/components/treeselect/treeselect.ts b/src/app/components/treeselect/treeselect.ts index a047fe893a1..bd25b384363 100755 --- a/src/app/components/treeselect/treeselect.ts +++ b/src/app/components/treeselect/treeselect.ts @@ -2,7 +2,7 @@ import { AnimationEvent } from '@angular/animations'; import { CommonModule } from '@angular/common'; import { AfterContentInit, ChangeDetectionStrategy, ChangeDetectorRef, Component, ContentChildren, ElementRef, EventEmitter, forwardRef, Input, NgModule, Output, QueryList, TemplateRef, ViewChild, ViewEncapsulation } from '@angular/core'; import { NG_VALUE_ACCESSOR } from '@angular/forms'; -import { OverlayOptions, OverlayService, PrimeNGConfig, PrimeTemplate, SharedModule, TreeNode } from 'primeng/api'; +import { OverlayOptions, OverlayService, PrimeNGConfig, PrimeTemplate, ScrollerOptions, SharedModule, TreeNode } from 'primeng/api'; import { DomHandler } from 'primeng/dom'; import { ChevronDownIcon } from 'primeng/icons/chevrondown'; import { SearchIcon } from 'primeng/icons/search'; @@ -133,6 +133,9 @@ export const TREESELECT_VALUE_ACCESSOR: any = { [filterPlaceholder]="filterPlaceholder" [filterLocale]="filterLocale" [filteredNodes]="filteredNodes" + [virtualScroll]="virtualScroll" + [virtualScrollItemSize]="virtualScrollItemSize" + [virtualScrollOptions]="virtualScrollOptions" [_templateMap]="templateMap" > @@ -314,6 +317,27 @@ export class TreeSelect implements AfterContentInit { * @group Props */ @Input() resetFilterOnHide: boolean = true; + /** + * Inline style of the tree component. + * @group Props + */ + @Input() treeStyle: { [klass: string]: any } | null | undefined; + + /** + * Whether the data should be loaded on demand during scroll. + * @group Props + */ + @Input() virtualScroll: boolean | undefined; + /** + * Height of an item in the list for VirtualScrolling. + * @group Props + */ + @Input() virtualScrollItemSize: number | undefined; + /** + * Whether to use the scroller feature. The properties of scroller component can be used like an object in it. + * @group Props + */ + @Input() virtualScrollOptions: ScrollerOptions | undefined; /** * An array of treenodes. * @defaultValue undefined diff --git a/src/app/showcase/doc/treeselect/treeselectdoc.module.ts b/src/app/showcase/doc/treeselect/treeselectdoc.module.ts index 3499d292ade..f683dee04b4 100644 --- a/src/app/showcase/doc/treeselect/treeselectdoc.module.ts +++ b/src/app/showcase/doc/treeselect/treeselectdoc.module.ts @@ -16,10 +16,11 @@ import { InvalidDoc } from './invaliddoc'; import { MultipleDoc } from './multipledoc'; import { ReactiveFormsDoc } from './reactiveformsdoc'; import { StyleDoc } from './styledoc'; +import { VirtualScrollDoc } from './virtualscrolldoc'; @NgModule({ imports: [CommonModule, AppCodeModule, AppDocModule, TreeSelectModule, FormsModule, ReactiveFormsModule, RouterModule], exports: [AppDocModule], - declarations: [ImportDoc, BasicDoc, MultipleDoc, CheckboxDoc, FilterDoc, FloatLabelDoc, InvalidDoc, DisabledDoc, StyleDoc, AccessibilityDoc, ReactiveFormsDoc] + declarations: [ImportDoc, BasicDoc, MultipleDoc, CheckboxDoc, VirtualScrollDoc, FilterDoc, FloatLabelDoc, InvalidDoc, DisabledDoc, StyleDoc, AccessibilityDoc, ReactiveFormsDoc] }) export class TreeSelectDocModule {} diff --git a/src/app/showcase/doc/treeselect/virtualscrolldoc.ts b/src/app/showcase/doc/treeselect/virtualscrolldoc.ts new file mode 100644 index 00000000000..f1fab20f117 --- /dev/null +++ b/src/app/showcase/doc/treeselect/virtualscrolldoc.ts @@ -0,0 +1,110 @@ +import { Component, Input } from '@angular/core'; +import { Code } from '../../domain/code'; +import { NodeService } from '../../service/nodeservice'; +import {TreeNode} from "../../../components/api/treenode"; + +@Component({ + selector: 'checkbox-doc', + template: `
+ +

Virtual scroll

+
+
+ +
+ +
` +}) +export class VirtualScrollDoc { + @Input() id: string; + + @Input() title: string; + + nodes!: any[]; + + selectedNodes: any; + + constructor(private nodeService: NodeService) { + // this.nodeService.getFiles().then((files) => (this.nodes = files)); + this.nodes = this.getMockedTreeNodes(10, 100); + } + + private getMockedTreeNodes(parentCount: number, childrenCount: number): TreeNode[] { + let nodes: TreeNode[] = []; + for (let i = 0; i < parentCount; i++) { + let node: TreeNode = { + key: i.toString(), + label: 'Parent ' + i, + selectable: true, + children: [] + }; + for (let j = 0; j < childrenCount; j++) { + node.children.push({ + key: i + '-' + j, + label: 'Child ' + i + '-' + j, + selectable: true, + }); + } + nodes.push(node); + } + return nodes; + } + + code: Code = { + basic: ``, + html: ` +
+ +
`, + + typescript: ` +import { Component } from '@angular/core'; +import { NodeService } from '../../service/nodeservice'; + +@Component({ + selector: 'tree-select-checkbox-demo', + templateUrl: './tree-select-checkbox-demo.html' +}) +export class TreeSelectCheckboxDemo { + nodes!: any[]; + + selectedNodes: any; + + constructor(private nodeService: NodeService) { + this.nodeService.getFiles().then((files) => (this.nodes = files)); + } +}`, + + service: ['NodeService'], + + data: ` + /* NodeService */ +{ + key: '0', + label: 'Documents', + data: 'Documents Folder', + icon: 'pi pi-fw pi-inbox', + children: [ + { + key: '0-0', + label: 'Work', + data: 'Work Folder', + icon: 'pi pi-fw pi-cog', + children: [ + { key: '0-0-0', label: 'Expenses.doc', icon: 'pi pi-fw pi-file', data: 'Expenses Document' }, + { key: '0-0-1', label: 'Resume.doc', icon: 'pi pi-fw pi-file', data: 'Resume Document' } + ] + }, + { + key: '0-1', + label: 'Home', + data: 'Home Folder', + icon: 'pi pi-fw pi-home', + children: [{ key: '0-1-0', label: 'Invoices.txt', icon: 'pi pi-fw pi-file', data: 'Invoices for this month' }] + } + ] +}, +...` + }; +} diff --git a/src/app/showcase/pages/treeselect/treeselectdemo.ts b/src/app/showcase/pages/treeselect/treeselectdemo.ts index d55f0958cac..ce3d7a9ede4 100644 --- a/src/app/showcase/pages/treeselect/treeselectdemo.ts +++ b/src/app/showcase/pages/treeselect/treeselectdemo.ts @@ -10,6 +10,7 @@ import { ImportDoc } from '../../doc/treeselect/importdoc'; import { InvalidDoc } from '../../doc/treeselect/invaliddoc'; import { MultipleDoc } from '../../doc/treeselect/multipledoc'; import { StyleDoc } from '../../doc/treeselect/styledoc'; +import { VirtualScrollDoc } from '../../doc/treeselect/virtualscrolldoc'; @Component({ templateUrl: './treeselectdemo.html' @@ -41,6 +42,11 @@ export class TreeSelectDemo { label: 'Checkbox', component: CheckboxDoc }, + { + id: 'virtual-scroll-doc', + label: 'Virtual Scroll', + component: VirtualScrollDoc + }, { id: 'filter', label: 'Filter', From a829b9bee8e8743071f05dccb6491c00d0a68eef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Rouzi=C3=A8s?= Date: Fri, 15 Sep 2023 15:25:19 +0200 Subject: [PATCH 2/8] Improve TreeSelect Virtual Scroll doc --- .../doc/treeselect/virtualscrolldoc.ts | 70 +++---------------- src/app/showcase/service/nodeservice.ts | 26 +++++++ 2 files changed, 35 insertions(+), 61 deletions(-) diff --git a/src/app/showcase/doc/treeselect/virtualscrolldoc.ts b/src/app/showcase/doc/treeselect/virtualscrolldoc.ts index f1fab20f117..1807e4e961c 100644 --- a/src/app/showcase/doc/treeselect/virtualscrolldoc.ts +++ b/src/app/showcase/doc/treeselect/virtualscrolldoc.ts @@ -1,19 +1,19 @@ import { Component, Input } from '@angular/core'; import { Code } from '../../domain/code'; import { NodeService } from '../../service/nodeservice'; -import {TreeNode} from "../../../components/api/treenode"; @Component({ - selector: 'checkbox-doc', + selector: 'virtual-scroll-doc', template: `
-

Virtual scroll

+

VirtualScrolling is an efficient way of rendering the options by displaying a small subset of data in the viewport at any time. When dealing with huge number of options, it is suggested to enable VirtualScrolling to avoid performance + issues. Usage is simple as setting virtualScroll property to true and defining virtualScrollItemSize to specify the height of an item.

- +
` }) export class VirtualScrollDoc { @@ -26,29 +26,7 @@ export class VirtualScrollDoc { selectedNodes: any; constructor(private nodeService: NodeService) { - // this.nodeService.getFiles().then((files) => (this.nodes = files)); - this.nodes = this.getMockedTreeNodes(10, 100); - } - - private getMockedTreeNodes(parentCount: number, childrenCount: number): TreeNode[] { - let nodes: TreeNode[] = []; - for (let i = 0; i < parentCount; i++) { - let node: TreeNode = { - key: i.toString(), - label: 'Parent ' + i, - selectable: true, - children: [] - }; - for (let j = 0; j < childrenCount; j++) { - node.children.push({ - key: i + '-' + j, - label: 'Child ' + i + '-' + j, - selectable: true, - }); - } - nodes.push(node); - } - return nodes; + this.nodeService.getLargeTreeNodes().then((files) => (this.nodes = files)); } code: Code = { @@ -57,54 +35,24 @@ export class VirtualScrollDoc {
`, - typescript: ` import { Component } from '@angular/core'; import { NodeService } from '../../service/nodeservice'; @Component({ - selector: 'tree-select-checkbox-demo', - templateUrl: './tree-select-checkbox-demo.html' + selector: 'tree-select-virtual-scroll-demo', + templateUrl: './tree-select-virtual-scroll-demo.html' }) -export class TreeSelectCheckboxDemo { +export class TreeSelectVirtualScrollDemo { nodes!: any[]; selectedNodes: any; constructor(private nodeService: NodeService) { - this.nodeService.getFiles().then((files) => (this.nodes = files)); + this.nodeService.getLargeTreeNodes().then((files) => (this.nodes = files)); } }`, service: ['NodeService'], - - data: ` - /* NodeService */ -{ - key: '0', - label: 'Documents', - data: 'Documents Folder', - icon: 'pi pi-fw pi-inbox', - children: [ - { - key: '0-0', - label: 'Work', - data: 'Work Folder', - icon: 'pi pi-fw pi-cog', - children: [ - { key: '0-0-0', label: 'Expenses.doc', icon: 'pi pi-fw pi-file', data: 'Expenses Document' }, - { key: '0-0-1', label: 'Resume.doc', icon: 'pi pi-fw pi-file', data: 'Resume Document' } - ] - }, - { - key: '0-1', - label: 'Home', - data: 'Home Folder', - icon: 'pi pi-fw pi-home', - children: [{ key: '0-1-0', label: 'Invoices.txt', icon: 'pi pi-fw pi-file', data: 'Invoices for this month' }] - } - ] -}, -...` }; } diff --git a/src/app/showcase/service/nodeservice.ts b/src/app/showcase/service/nodeservice.ts index 8f306a1d432..9e3b99c7f48 100755 --- a/src/app/showcase/service/nodeservice.ts +++ b/src/app/showcase/service/nodeservice.ts @@ -1,4 +1,5 @@ import { Injectable } from '@angular/core'; +import { TreeNode } from "../../components/api/treenode"; @Injectable() export class NodeService { @@ -763,6 +764,31 @@ export class NodeService { ]; } + getDynamicTreeNodes(parentCount: number, childrenCount: number): TreeNode[] { + const nodes: TreeNode[] = []; + for (let index = 0; index < parentCount; index++) { + const node: TreeNode = { + key: index.toString(), + label: 'Parent ' + index, + selectable: true, + children: [] + }; + for (let j = 0; j < childrenCount; j++) { + node.children.push({ + key: index + '-' + j, + label: 'Child ' + index + '-' + j, + selectable: true, + }); + } + nodes.push(node); + } + return nodes; + } + + getLargeTreeNodes() { + return Promise.resolve(this.getDynamicTreeNodes(10, 100)); + } + getTreeTableNodes() { return Promise.resolve(this.getTreeTableNodesData()); } From c9a5a6b3370a1ec3689d69adfa2b1ea69e9982b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Rouzi=C3=A8s?= Date: Thu, 28 Sep 2023 10:43:28 +0200 Subject: [PATCH 3/8] Add css when treeselect has virtual scroll enabled --- src/app/components/treeselect/treeselect.css | 10 +++++++++- src/app/components/treeselect/treeselect.ts | 2 +- src/app/showcase/doc/treeselect/virtualscrolldoc.ts | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/src/app/components/treeselect/treeselect.css b/src/app/components/treeselect/treeselect.css index 5479469e6d6..4efcd30dd00 100755 --- a/src/app/components/treeselect/treeselect.css +++ b/src/app/components/treeselect/treeselect.css @@ -92,4 +92,12 @@ .p-treeselect-clearable { position: relative; -} +} + +.p-treeselect-virtual-scroll .p-tree.p-component { + padding: 0; +} + +.p-treeselect-virtual-scroll .p-tree-container.p-scroller-content { + padding: 1.25rem; +} diff --git a/src/app/components/treeselect/treeselect.ts b/src/app/components/treeselect/treeselect.ts index bd25b384363..282a0d3625e 100755 --- a/src/app/components/treeselect/treeselect.ts +++ b/src/app/components/treeselect/treeselect.ts @@ -113,7 +113,7 @@ export const TREESELECT_VALUE_ACCESSOR: any = { -
+
+ [virtualScroll]="true" [virtualScrollItemSize]="40" [virtualScrollOptions]="{ scrollHeight: '200px' }">
` From 7bd96a5a774252dedc130a8966ca3dbf51fac473 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Rouzi=C3=A8s?= Date: Thu, 28 Sep 2023 10:46:30 +0200 Subject: [PATCH 4/8] Remove unused @Input() --- src/app/components/treeselect/treeselect.ts | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/app/components/treeselect/treeselect.ts b/src/app/components/treeselect/treeselect.ts index 282a0d3625e..e55c78bfa85 100755 --- a/src/app/components/treeselect/treeselect.ts +++ b/src/app/components/treeselect/treeselect.ts @@ -317,12 +317,6 @@ export class TreeSelect implements AfterContentInit { * @group Props */ @Input() resetFilterOnHide: boolean = true; - /** - * Inline style of the tree component. - * @group Props - */ - @Input() treeStyle: { [klass: string]: any } | null | undefined; - /** * Whether the data should be loaded on demand during scroll. * @group Props From 0f8e514ee5974cf21b0b7edf854e39338da46a70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ga=C3=ABtan=20Rouzi=C3=A8s?= Date: Fri, 29 Sep 2023 11:08:02 +0200 Subject: [PATCH 5/8] Clean getDynamicTreeNodes function and fix virtual scroll item size --- .../doc/treeselect/virtualscrolldoc.ts | 6 ++-- src/app/showcase/service/nodeservice.ts | 28 +++++++++++-------- 2 files changed, 19 insertions(+), 15 deletions(-) diff --git a/src/app/showcase/doc/treeselect/virtualscrolldoc.ts b/src/app/showcase/doc/treeselect/virtualscrolldoc.ts index 567b4935fba..aef14be8b6a 100644 --- a/src/app/showcase/doc/treeselect/virtualscrolldoc.ts +++ b/src/app/showcase/doc/treeselect/virtualscrolldoc.ts @@ -11,7 +11,7 @@ import { NodeService } from '../../service/nodeservice';
+ [virtualScroll]="true" [virtualScrollItemSize]="46" [virtualScrollOptions]="{ scrollHeight: '200px' }">
` @@ -30,10 +30,10 @@ export class VirtualScrollDoc { } code: Code = { - basic: ``, + basic: ``, html: `
- +
`, typescript: ` import { Component } from '@angular/core'; diff --git a/src/app/showcase/service/nodeservice.ts b/src/app/showcase/service/nodeservice.ts index 9e3b99c7f48..35f390d08f2 100755 --- a/src/app/showcase/service/nodeservice.ts +++ b/src/app/showcase/service/nodeservice.ts @@ -766,22 +766,26 @@ export class NodeService { getDynamicTreeNodes(parentCount: number, childrenCount: number): TreeNode[] { const nodes: TreeNode[] = []; - for (let index = 0; index < parentCount; index++) { - const node: TreeNode = { - key: index.toString(), - label: 'Parent ' + index, - selectable: true, - children: [] - }; - for (let j = 0; j < childrenCount; j++) { - node.children.push({ - key: index + '-' + j, - label: 'Child ' + index + '-' + j, + + for (let parentIndex = 0; parentIndex < parentCount; parentIndex++) { + const children: TreeNode[] = []; + + for (let childIndex = 0; childIndex < childrenCount; childIndex++) { + children.push({ + key: `${parentIndex}-${childIndex}`, + label: `Child ${parentIndex}-${childIndex}`, selectable: true, }); } - nodes.push(node); + + nodes.push({ + key: parentIndex.toString(), + label: `Parent ${parentIndex}`, + selectable: true, + children: children, + }); } + return nodes; } From 3e6a4fb49cdd64fc884aad109efd1b554660d897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87etin?= <69278826+cetincakiroglu@users.noreply.github.com> Date: Fri, 22 Mar 2024 18:02:07 +0300 Subject: [PATCH 6/8] Update treeselect.css Remove unnecessary css --- src/app/components/treeselect/treeselect.css | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/app/components/treeselect/treeselect.css b/src/app/components/treeselect/treeselect.css index 763def23d7f..f6e980edc16 100755 --- a/src/app/components/treeselect/treeselect.css +++ b/src/app/components/treeselect/treeselect.css @@ -94,12 +94,4 @@ .p-treeselect-clearable { position: relative; } - - .p-treeselect-virtual-scroll .p-tree.p-component { - padding: 0; - } - - .p-treeselect-virtual-scroll .p-tree-container.p-scroller-content { - padding: 1.25rem; - } } From 250509e9d7111a670ecc8063b98f4a3fd3527714 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=87etin?= <69278826+cetincakiroglu@users.noreply.github.com> Date: Fri, 22 Mar 2024 18:02:57 +0300 Subject: [PATCH 7/8] Update treeselect.ts --- src/app/components/treeselect/treeselect.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app/components/treeselect/treeselect.ts b/src/app/components/treeselect/treeselect.ts index ffdf3646121..4950a01f41d 100755 --- a/src/app/components/treeselect/treeselect.ts +++ b/src/app/components/treeselect/treeselect.ts @@ -113,7 +113,7 @@ export const TREESELECT_VALUE_ACCESSOR: any = {
-
+
Date: Fri, 22 Mar 2024 18:03:59 +0300 Subject: [PATCH 8/8] Update virtualscrolldoc.ts --- src/app/showcase/doc/treeselect/virtualscrolldoc.ts | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/app/showcase/doc/treeselect/virtualscrolldoc.ts b/src/app/showcase/doc/treeselect/virtualscrolldoc.ts index aef14be8b6a..81d617a48c9 100644 --- a/src/app/showcase/doc/treeselect/virtualscrolldoc.ts +++ b/src/app/showcase/doc/treeselect/virtualscrolldoc.ts @@ -4,8 +4,8 @@ import { NodeService } from '../../service/nodeservice'; @Component({ selector: 'virtual-scroll-doc', - template: `
- + template: ` +

VirtualScrolling is an efficient way of rendering the options by displaying a small subset of data in the viewport at any time. When dealing with huge number of options, it is suggested to enable VirtualScrolling to avoid performance issues. Usage is simple as setting virtualScroll property to true and defining virtualScrollItemSize to specify the height of an item.

@@ -13,13 +13,9 @@ import { NodeService } from '../../service/nodeservice';
- - ` + ` }) export class VirtualScrollDoc { - @Input() id: string; - - @Input() title: string; nodes!: any[];