diff --git a/libs/components/ag-grid/src/lib/modules/ag-grid/ag-grid-row-delete.directive.spec.ts b/libs/components/ag-grid/src/lib/modules/ag-grid/ag-grid-row-delete.directive.spec.ts index 47cdb19693..4099d28add 100644 --- a/libs/components/ag-grid/src/lib/modules/ag-grid/ag-grid-row-delete.directive.spec.ts +++ b/libs/components/ag-grid/src/lib/modules/ag-grid/ag-grid-row-delete.directive.spec.ts @@ -1,4 +1,9 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; +import { + ComponentFixture, + TestBed, + fakeAsync, + tick, +} from '@angular/core/testing'; import { SKY_STACKING_CONTEXT, SkyScrollableHostService } from '@skyux/core'; import { BehaviorSubject, Observable, of } from 'rxjs'; @@ -158,18 +163,18 @@ describe('SkyAgGridRowDeleteDirective', () => { ).toBe(2); }); - it('should respond dataset changes', async () => { + it('should respond dataset changes', fakeAsync(() => { setupTest(); - await fixture.whenStable(); + tick(16); fixture.componentInstance.rowDeleteIds = ['0', '2']; fixture.detectChanges(); - await fixture.whenStable(); + tick(16); fixture.componentInstance.removeFirstItem(); fixture.detectChanges(); - await fixture.whenStable(); + tick(16); expect(fixture.componentInstance.rowDeleteIds).toEqual(['2']); expect(document.querySelector('#row-delete-ref-0')).toBeNull(); @@ -177,7 +182,7 @@ describe('SkyAgGridRowDeleteDirective', () => { expect( document.querySelectorAll('.sky-inline-delete-standard').length, ).toBe(1); - }); + })); }); it('should cancel row delete elements correctly via them being removed from the id array', async () => { diff --git a/libs/components/ag-grid/src/lib/modules/ag-grid/ag-grid-row-delete.directive.ts b/libs/components/ag-grid/src/lib/modules/ag-grid/ag-grid-row-delete.directive.ts index d536bdeceb..f90ea9e637 100644 --- a/libs/components/ag-grid/src/lib/modules/ag-grid/ag-grid-row-delete.directive.ts +++ b/libs/components/ag-grid/src/lib/modules/ag-grid/ag-grid-row-delete.directive.ts @@ -2,7 +2,6 @@ import { AfterContentInit, AfterViewInit, ChangeDetectorRef, - ContentChild, Directive, ElementRef, EnvironmentInjector, @@ -11,6 +10,8 @@ import { OnDestroy, Output, ViewContainerRef, + contentChild, + effect, inject, } from '@angular/core'; import { @@ -25,7 +26,13 @@ import { import { AgGridAngular } from 'ag-grid-angular'; import { IRowNode } from 'ag-grid-community'; -import { BehaviorSubject, Subject } from 'rxjs'; +import { + BehaviorSubject, + Subject, + animationFrames, + debounce, + merge, +} from 'rxjs'; import { takeUntil } from 'rxjs/operators'; import { SkyAgGridRowDeleteComponent } from './ag-grid-row-delete.component'; @@ -83,7 +90,7 @@ export class SkyAgGridRowDeleteDirective overlay.attachTemplate( this.#rowDeleteComponent.inlineDeleteTemplateRef, { - $implicit: this.agGrid.api.getRowNode(id), + $implicit: this.agGrid()?.api.getRowNode(id), tableWidth: () => this.#elementRef.nativeElement.querySelector('.sky-ag-grid') .offsetWidth, @@ -162,8 +169,7 @@ export class SkyAgGridRowDeleteDirective #rowDeleteConfigs: SkyAgGridRowDeleteConfig[] = []; - @ContentChild(AgGridAngular) - public agGrid: AgGridAngular | undefined; + public agGrid = contentChild(AgGridAngular); #ngUnsubscribe = new Subject(); #rowDeleteComponent: SkyAgGridRowDeleteComponent | undefined; @@ -183,6 +189,7 @@ export class SkyAgGridRowDeleteDirective readonly #scrollableHostService = inject(SkyScrollableHostService); readonly #stackingContext = inject(SKY_STACKING_CONTEXT, { optional: true }); readonly #viewContainerRef = inject(ViewContainerRef); + readonly #viewInit = new Subject(); constructor() { this.#hasStackingContext = !!this.#stackingContext; @@ -194,6 +201,26 @@ export class SkyAgGridRowDeleteDirective this.#zIndex.next(zIndex); }); } + effect(() => { + const agGrid = this.agGrid(); + if (agGrid) { + merge( + agGrid.filterChanged, + agGrid.firstDataRendered, + agGrid.gridReady, + agGrid.rowDataUpdated, + agGrid.sortChanged, + this.#viewInit, + ) + .pipe( + takeUntil(this.#ngUnsubscribe), + debounce(() => animationFrames()), + ) + .subscribe(() => { + this.#updateRowDeleteStates(); + }); + } + }); } public ngAfterContentInit(): void { @@ -204,26 +231,6 @@ export class SkyAgGridRowDeleteDirective viewContainerRef: this.#viewContainerRef, }, ).instance; - - if (this.agGrid) { - this.agGrid.rowDataUpdated - .pipe(takeUntil(this.#ngUnsubscribe)) - .subscribe(() => { - this.#updateRowDeleteStates(); - }); - - this.agGrid.sortChanged - .pipe(takeUntil(this.#ngUnsubscribe)) - .subscribe(() => { - this.#updateRowDeleteStates(); - }); - - this.agGrid.filterChanged - .pipe(takeUntil(this.#ngUnsubscribe)) - .subscribe(() => { - this.#updateRowDeleteStates(); - }); - } } public ngAfterViewInit(): void { @@ -235,6 +242,7 @@ export class SkyAgGridRowDeleteDirective this.#clipPath.next(clipPath); }); } + this.#viewInit.next(); } public ngOnDestroy(): void { @@ -292,26 +300,21 @@ export class SkyAgGridRowDeleteDirective #destroyRowDelete(id: string): void { const rowDeleteContents = this.#rowDeleteContents[id]; - - /* sanity check */ - /* istanbul ignore else */ - if (rowDeleteContents) { - rowDeleteContents.affixer.destroy(); - this.#overlayService.close(rowDeleteContents.overlay); - delete this.#rowDeleteContents[id]; - this.#rowDeleteConfigs = this.#rowDeleteConfigs.filter( - (config) => config.id !== id, - ); - this.#rowDeleteIdsInternal = this.rowDeleteIds?.filter( - (arrayId) => arrayId !== id, - ); - this.rowDeleteIdsChange.emit(this.#rowDeleteIdsInternal); - } + rowDeleteContents?.affixer.destroy(); + this.#overlayService.close(rowDeleteContents?.overlay); + delete this.#rowDeleteContents[id]; + this.#rowDeleteConfigs = this.#rowDeleteConfigs.filter( + (config) => config.id !== id, + ); + this.#rowDeleteIdsInternal = this.rowDeleteIds?.filter( + (arrayId) => arrayId !== id, + ); + this.rowDeleteIdsChange.emit(this.#rowDeleteIdsInternal); } #updateRowDeleteStates(): void { this.#rowDeleteConfigs.forEach((config: SkyAgGridRowDeleteConfig) => { - if (!this.agGrid?.api.getRowNode(config.id)) { + if (!this.agGrid()?.api.getRowNode(config.id)) { this.#destroyRowDelete(config.id); } else { // We must reaffix things when the data changes because the rows rerender and the previous element that the delete was affixed diff --git a/libs/components/ag-grid/src/lib/modules/ag-grid/fixtures/ag-grid-row-delete.component.fixture.ts b/libs/components/ag-grid/src/lib/modules/ag-grid/fixtures/ag-grid-row-delete.component.fixture.ts index 0069280b5a..dd2a7bec29 100644 --- a/libs/components/ag-grid/src/lib/modules/ag-grid/fixtures/ag-grid-row-delete.component.fixture.ts +++ b/libs/components/ag-grid/src/lib/modules/ag-grid/fixtures/ag-grid-row-delete.component.fixture.ts @@ -111,6 +111,7 @@ export class SkyAgGridRowDeleteFixtureComponent implements OnInit { public changeToLongData(): void { this.gridData = SKY_AG_GRID_LONG_DATA; + this.gridApi?.setGridOption('rowData', this.gridData); } public filterName(): Promise { @@ -160,6 +161,7 @@ export class SkyAgGridRowDeleteFixtureComponent implements OnInit { public removeFirstItem(): void { this.gridData = this.gridData.slice(1); + this.gridApi?.setGridOption('rowData', this.gridData); } public sortName(): Promise {