From f612626e38b7b46031f900702bc09ed546fd8eb6 Mon Sep 17 00:00:00 2001 From: Svetoslav Krastev Date: Fri, 23 Feb 2024 12:31:54 +0200 Subject: [PATCH] Add toolbar and paginator template inputs enhancements. Optimize paginator init. (#13942) --- CHANGELOG.md | 2 + .../src/lib/grids/common/grid.interface.ts | 4 ++ .../hierarchical-grid.integration.spec.ts | 36 ++++++++++- .../hierarchical-grid/row-island.component.ts | 60 ++++++++++++++++--- .../hierarchical-grid-components.spec.ts | 49 ++++++++++++++- 5 files changed, 140 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e42644df0e3..de9b53a14bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,6 +25,8 @@ All notable changes for each version of this project will be documented in this - New directive - `igxIconButton` directive that provides a way to use an icon as a fully functional button has been added. The new `igxIconButton` comes in three types - flat, outlined and contained (default). All `igxButton`'s with type `icon` will be automatically migrated to the new `igxIconButton`'s with `ng update`. - `IgxButton` - **Behavioral Change** `buttonSelected` event is now emitted not only when a button gets selected, but also when it gets deselected. However, the event is no longer being emitted on initialization. If this event was used in a scenario where it is assumed that the button gets selected, it's a good idea the logic to be branched now based on `eventArgs.selected` condition. +- `IgxRowIsland` + - Added `toolbarTemplate` and `paginatorTemplate` inputs for defining `IgxGridToolbar` and `IgxPaginator` templates. ### General diff --git a/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts b/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts index b98038b027c..8a1f8e33c68 100644 --- a/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts +++ b/projects/igniteui-angular/src/lib/grids/common/grid.interface.ts @@ -1388,6 +1388,10 @@ export interface IgxSummaryTemplateContext { $implicit: IgxSummaryResult[] } +export interface IgxGridPaginatorTemplateContext { + $implicit: GridType; +} + /** * An interface describing settings for row/column pinning position. */ diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.integration.spec.ts b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.integration.spec.ts index 8648c0d6584..ba01eb3d785 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.integration.spec.ts +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.integration.spec.ts @@ -12,6 +12,8 @@ import { take } from 'rxjs/operators'; import { IgxHierarchicalGridTestBaseComponent, IgxHierarchicalGridTestCustomToolbarComponent, + IgxHierarchicalGridTestInputPaginatorComponent, + IgxHierarchicalGridTestInputToolbarComponent, IgxHierarchicalGridWithTransactionProviderComponent } from '../../test-utils/hierarchical-grid-components.spec'; import { GridFunctions, GridSelectionFunctions } from '../../test-utils/grid-functions.spec'; @@ -39,7 +41,9 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { NoopAnimationsModule, IgxHierarchicalGridTestBaseComponent, IgxHierarchicalGridTestCustomToolbarComponent, - IgxHierarchicalGridWithTransactionProviderComponent + IgxHierarchicalGridWithTransactionProviderComponent, + IgxHierarchicalGridTestInputPaginatorComponent, + IgxHierarchicalGridTestInputToolbarComponent ] }).compileComponents(); })) @@ -639,6 +643,21 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { expect(hierarchicalGrid.hasVerticalScroll()).toBeTruthy(); })); + + it('should be displayed correctly when using the template input', fakeAsync(() => { + fixture = TestBed.createComponent(IgxHierarchicalGridTestInputPaginatorComponent); + tick(); + fixture.detectChanges(); + hierarchicalGrid = fixture.componentInstance.hgrid; + + hierarchicalGrid.expandRow(hierarchicalGrid.dataRowList.first.key); + tick(DEBOUNCE_TIME); + fixture.detectChanges(); + + const paginators = fixture.debugElement.queryAll(By.css('igx-paginator')); + expect(paginators[0].query(By.css('button')).nativeElement.innerText.trim()).toEqual('childData1 Button'); + expect(paginators[1].query(By.css('button')).nativeElement.innerText.trim()).toEqual('childData2 Button'); + })) }); describe('Hiding', () => { @@ -774,6 +793,21 @@ describe('IgxHierarchicalGrid Integration #hGrid', () => { const toolbar = fixture.debugElement.query(By.css('igx-grid-toolbar')); expect(toolbar.nativeElement.offsetWidth).toEqual(hierarchicalGrid.nativeElement.offsetWidth); })); + + it('should be displayed correctly when using the template input', fakeAsync(() => { + fixture = TestBed.createComponent(IgxHierarchicalGridTestInputToolbarComponent); + tick(); + fixture.detectChanges(); + hierarchicalGrid = fixture.componentInstance.hgrid; + + hierarchicalGrid.expandRow(hierarchicalGrid.dataRowList.first.key); + tick(DEBOUNCE_TIME); + fixture.detectChanges(); + + const toolbars = fixture.debugElement.queryAll(By.css('igx-grid-toolbar')); + expect(toolbars[1].query(By.css('button')).nativeElement.innerText.trim()).toEqual('childData1 Button'); + expect(toolbars[2].query(By.css('button')).nativeElement.innerText.trim()).toEqual('childData2 Button'); + })) }); describe('Moving', () => { diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/row-island.component.ts b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/row-island.component.ts index 375253dce6b..fa09731b2a7 100644 --- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/row-island.component.ts +++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/row-island.component.ts @@ -41,7 +41,7 @@ import { IgxColumnComponent } from '../columns/column.component'; import { IgxRowIslandAPIService } from './row-island-api.service'; import { PlatformUtil } from '../../core/utils'; import { IgxColumnResizingService } from '../resizing/resizing.service'; -import { GridType, IGX_GRID_SERVICE_BASE } from '../common/grid.interface'; +import { GridType, IGX_GRID_SERVICE_BASE, IgxGridPaginatorTemplateContext } from '../common/grid.interface'; import { IgxGridToolbarDirective, IgxGridToolbarTemplateContext } from '../toolbar/common'; import { IgxActionStripToken } from '../../action-strip/token'; import { IgxPaginatorDirective } from '../../paginator/paginator-interfaces'; @@ -49,6 +49,7 @@ import { IgxFlatTransactionFactory } from '../../services/transaction/transactio import { IGridCreatedEventArgs } from './events'; import { IgxGridValidationService } from '../grid/grid-validation.service'; import { IgxTextHighlightService } from '../../directives/text-highlight/text-highlight.service'; +import { IgxPaginatorComponent } from '../../paginator/paginator.component'; @Component({ changeDetection: ChangeDetectionStrategy.OnPush, @@ -90,15 +91,47 @@ export class IgxRowIslandComponent extends IgxHierarchicalGridBaseDirective @ContentChildren(IgxColumnComponent, { read: IgxColumnComponent, descendants: false }) public childColumns = new QueryList(); + /** + * @hidden + * @internal + */ @ContentChild(IgxGridToolbarDirective, { read: TemplateRef }) - public islandToolbarTemplate: TemplateRef; + protected toolbarDirectiveTemplate: TemplateRef; + /** + * @hidden + * @internal + */ @ContentChild(IgxPaginatorDirective, { read: TemplateRef }) - public islandPaginatorTemplate: TemplateRef; + protected paginatorDirectiveTemplate: TemplateRef; + + /** + * Sets/Gets the toolbar template for each child grid created from this row island. + */ + @Input() + public get toolbarTemplate(): TemplateRef { + return this._toolbarTemplate || this.toolbarDirectiveTemplate; + } + + public set toolbarTemplate(template: TemplateRef) { + this._toolbarTemplate = template; + } + + /** + * Sets/Gets the paginator template for each child grid created from this row island. + */ + @Input() + public get paginatorTemplate(): TemplateRef { + return this._paginatorTemplate || this.paginatorDirectiveTemplate; + } + + public set paginatorTemplate(template: TemplateRef) { + this._paginatorTemplate = template; + } /** @hidden @internal **/ @ContentChildren(IgxActionStripToken, { read: IgxActionStripToken, descendants: false }) - public actionStrips: QueryList; + protected actionStrips: QueryList; /** * @hidden @@ -151,6 +184,8 @@ export class IgxRowIslandComponent extends IgxHierarchicalGridBaseDirective private ri_columnListDiffer; private layout_id = `igx-row-island-`; private isInit = false; + private _toolbarTemplate: TemplateRef; + private _paginatorTemplate: TemplateRef; /** * Sets if all immediate children of the grids for this `IgxRowIslandComponent` should be expanded/collapsed. @@ -333,12 +368,19 @@ export class IgxRowIslandComponent extends IgxHierarchicalGridBaseDirective // Create the child toolbar if the parent island has a toolbar definition this.gridCreated.pipe(pluck('grid'), takeUntil(this.destroy$)).subscribe(grid => { - grid.rendered$.pipe(first(), filter(() => !!this.islandToolbarTemplate)) - .subscribe(() => grid.toolbarOutlet.createEmbeddedView(this.islandToolbarTemplate, { $implicit: grid }, { injector: grid.toolbarOutlet.injector })); - grid.rendered$.pipe(first(), filter(() => !!this.islandPaginatorTemplate)) + grid.rendered$.pipe(first(), filter(() => !!this.toolbarTemplate)) + .subscribe(() => grid.toolbarOutlet.createEmbeddedView(this.toolbarTemplate, { $implicit: grid }, { injector: grid.toolbarOutlet.injector })); + grid.rendered$.pipe(first(), filter(() => !!this.paginatorTemplate)) .subscribe(() => { - this.rootGrid.paginatorList.changes.pipe(takeUntil(this.destroy$)).subscribe(() => grid.setUpPaginator()); - grid.paginatorOutlet.createEmbeddedView(this.islandPaginatorTemplate); + this.rootGrid.paginatorList.changes.pipe(takeUntil(this.destroy$)).subscribe((changes: QueryList) => { + changes.forEach(p => { + if (p.nativeElement.offsetParent?.id === grid.id) { + // Optimize update only for those grids that have related changed paginator. + grid.setUpPaginator() + } + }); + }); + grid.paginatorOutlet.createEmbeddedView(this.paginatorTemplate, { $implicit: grid }); }); }); } diff --git a/projects/igniteui-angular/src/lib/test-utils/hierarchical-grid-components.spec.ts b/projects/igniteui-angular/src/lib/test-utils/hierarchical-grid-components.spec.ts index c78d7f19446..e12fa17411e 100644 --- a/projects/igniteui-angular/src/lib/test-utils/hierarchical-grid-components.spec.ts +++ b/projects/igniteui-angular/src/lib/test-utils/hierarchical-grid-components.spec.ts @@ -11,7 +11,7 @@ import { IgxHierarchicalTransactionServiceFactory } from '../grids/hierarchical- import { IgxGridToolbarComponent } from '../grids/toolbar/grid-toolbar.component'; import { IgxButtonDirective } from '../directives/button/button.directive'; import { IgxCheckboxComponent } from '../checkbox/checkbox.component'; -import { IgxPaginatorComponent } from '../paginator/paginator.component'; +import { IgxPaginatorComponent, IgxPaginatorContentDirective } from '../paginator/paginator.component'; import { IgxColumnGroupComponent } from '../grids/columns/column-group.component'; import { IgxIconComponent } from '../icon/icon.component'; import { IgxHeadSelectorDirective, IgxRowSelectorDirective } from '../grids/selection/row-selectors'; @@ -370,6 +370,53 @@ export class IgxHierarchicalGridCustomSelectorsComponent implements OnInit { }) export class IgxHierarchicalGridTestCustomToolbarComponent extends IgxHierarchicalGridTestBaseComponent { } +@Component({ + template: ` + + + + + + + + + + + + + + + `, + standalone: true, + imports: [IgxHierarchicalGridComponent, IgxGridToolbarComponent, IgxGridToolbarDirective, IgxRowIslandComponent, IgxButtonDirective] +}) +export class IgxHierarchicalGridTestInputToolbarComponent extends IgxHierarchicalGridTestBaseComponent { } + +@Component({ + template: ` + + + + + + + + + + + + + + + + `, + standalone: true, + imports: [IgxHierarchicalGridComponent, IgxGridToolbarComponent, IgxPaginatorComponent, IgxPaginatorContentDirective, IgxRowIslandComponent, IgxButtonDirective] +}) +export class IgxHierarchicalGridTestInputPaginatorComponent extends IgxHierarchicalGridTestBaseComponent { } + @Component({ template: `