diff --git a/projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts b/projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts
index 2a6bd5dc461..b269289efe7 100644
--- a/projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts
+++ b/projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts
@@ -11,6 +11,9 @@ import {
IgcColumnComponent,
IgcPaginatorComponent,
IgcGridStateComponent,
+ IgcColumnLayoutComponent,
+ IgcActionStripComponent,
+ IgcGridEditingActionsComponent,
} from './components';
import { defineComponents } from '../utils/register';
@@ -25,6 +28,8 @@ describe('Elements: ', () => {
IgcColumnComponent,
IgcPaginatorComponent,
IgcGridStateComponent,
+ IgcActionStripComponent,
+ IgcGridEditingActionsComponent
);
});
@@ -181,5 +186,66 @@ describe('Elements: ', () => {
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 2));
expect(() => stateComponent.getStateAsString()).not.toThrow();
});
+
+ it('should not destroy action strip when row it is shown in is destroyed or cached.', async() => {
+ const innerHtml = `
+
+
+
+
+ `;
+ testContainer.innerHTML = innerHtml;
+
+ // TODO: Better way to wait - potentially expose the queue or observable for update on the strategy
+ await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
+
+ const grid = document.querySelector>('#testGrid');
+ const actionStrip = document.querySelector>('#testStrip');
+ grid.data = SampleTestData.foodProductData();
+
+ // TODO: Better way to wait - potentially expose the queue or observable for update on the strategy
+ await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
+
+ let row = grid.dataRowList.toArray()[0];
+ actionStrip.show(row);
+ await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
+
+ expect(actionStrip.hidden).toBeFalse();
+
+ grid.data = [];
+ await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
+
+ // row destroyed
+ expect((row.cdr as any).destroyed).toBeTrue();
+ // action strip still in DOM, only hidden.
+ expect(actionStrip.hidden).toBeTrue();
+ expect(actionStrip.isConnected).toBeTrue();
+
+ grid.data = SampleTestData.foodProductData();
+ grid.groupBy({ fieldName: 'InStock', dir: 1, ignoreCase: false });
+
+ // TODO: Better way to wait - potentially expose the queue or observable for update on the strategy
+ await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
+
+ row = grid.dataRowList.toArray()[0];
+ actionStrip.show(row);
+ await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
+
+ expect(actionStrip.hidden).toBeFalse();
+
+ // collapse all data rows, leave only groups
+ grid.toggleAllGroupRows();
+
+ // TODO: Better way to wait - potentially expose the queue or observable for update on the strategy
+ await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
+
+ // row not destroyed, but also not in dom anymore
+ expect((row.cdr as any).destroyed).toBeFalse();
+ expect(row.element.nativeElement.isConnected).toBe(false);
+
+ // action strip still in DOM, only hidden.
+ expect(actionStrip.hidden).toBeTrue();
+ expect(actionStrip.isConnected).toBeTrue();
+ });
});
});
diff --git a/projects/igniteui-angular-elements/src/app/custom-strategy.ts b/projects/igniteui-angular-elements/src/app/custom-strategy.ts
index 1907cba1fe7..bfef980e8a9 100644
--- a/projects/igniteui-angular-elements/src/app/custom-strategy.ts
+++ b/projects/igniteui-angular-elements/src/app/custom-strategy.ts
@@ -126,6 +126,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
parentComponentRef = await parent?.ngElementStrategy[ComponentRefKey];
parentAnchor = parentComponentRef?.instance.anchor;
}
+
} else if ((parent as any)?.__componentRef) {
this.angularParent = (parent as any).__componentRef;
parentInjector = this.angularParent.injector;
diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts
index 4a86a58fdf4..34750256cd2 100644
--- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts
+++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts
@@ -15,6 +15,7 @@ import { IgxGridPinningActionsComponent } from './grid-pinning-actions.component
import { IgxActionStripComponent } from '../action-strip.component';
import { IRowDataCancelableEventArgs, IgxColumnComponent } from '../../grids/public_api';
import { SampleTestData } from '../../test-utils/sample-test-data.spec';
+import { SortingDirection } from '../../data-operations/sorting-strategy';
describe('igxGridEditingActions #grid ', () => {
let fixture;
@@ -274,6 +275,59 @@ describe('igxGridEditingActions #grid ', () => {
expect(actionStrip.hidden).toBeTrue();
});
+
+ it('should auto-hide on delete action click.', () => {
+ const row = grid.rowList.toArray()[0];
+ actionStrip.show(row);
+ fixture.detectChanges();
+
+ expect(actionStrip.hidden).toBeFalse();
+
+ const deleteIcon = fixture.debugElement.queryAll(By.css(`igx-grid-editing-actions igx-icon`))[1];
+ expect(deleteIcon.nativeElement.innerText).toBe('delete');
+ deleteIcon.parent.triggerEventHandler('click', new Event('click'));
+ fixture.detectChanges();
+
+ expect(actionStrip.hidden).toBeTrue();
+
+ });
+
+ it('should auto-hide if context row is destroyed.', () => {
+ const row = grid.rowList.toArray()[0];
+ actionStrip.show(row);
+ fixture.detectChanges();
+
+ expect(actionStrip.hidden).toBeFalse();
+
+ // bind to no data, which removes all rows.
+ grid.data = [];
+ grid.cdr.detectChanges();
+
+ expect((row.cdr as any).destroyed).toBeTrue();
+ expect(actionStrip.hidden).toBeTrue();
+ });
+
+ it('should auto-hide if context row is cached.', () => {
+ // create group rows
+ grid.groupBy({ fieldName: 'ContactTitle', dir: SortingDirection.Desc, ignoreCase: false });
+ fixture.detectChanges();
+
+ // show for first data row
+ const row = grid.dataRowList.toArray()[0];
+ actionStrip.show(row);
+ fixture.detectChanges();
+
+ // collapse all groups to cache data rows
+ grid.toggleAllGroupRows();
+ fixture.detectChanges();
+
+ // not destroyed, but not in DOM anymore
+ expect((row.cdr as any).destroyed).toBeFalse();
+ expect(row.element.nativeElement.isConnected).toBe(false);
+
+ // action strip should be hidden
+ expect(actionStrip.hidden).toBeTrue();
+ });
});
describe('auto show/hide in HierarchicalGrid', () => {
diff --git a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.ts b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.ts
index e48ec8745f2..4207450cb45 100644
--- a/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.ts
+++ b/projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.ts
@@ -147,7 +147,6 @@ export class IgxGridEditingActionsComponent extends IgxGridActionsBaseDirective
const context = this.strip.context;
const grid = context.grid;
grid.deleteRow(context.key);
-
this.strip.hide();
}
diff --git a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts
index 8bd23768c0b..42e25b657bc 100644
--- a/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts
+++ b/projects/igniteui-angular/src/lib/grids/grid-base.directive.ts
@@ -6205,6 +6205,12 @@ export abstract class IgxGridBaseDirective implements GridType,
}
}
+ protected viewDetachHandler(args) {
+ if (this.actionStrip && args.view.rootNodes.find(x => x === this.actionStrip.context?.element.nativeElement)) {
+ this.actionStrip.hide();
+ }
+ }
+
/**
* @hidden @internal
*/
diff --git a/projects/igniteui-angular/src/lib/grids/grid/grid.component.html b/projects/igniteui-angular/src/lib/grids/grid/grid.component.html
index f20ed0502ab..ed959819058 100644
--- a/projects/igniteui-angular/src/lib/grids/grid/grid.component.html
+++ b/projects/igniteui-angular/src/lib/grids/grid/grid.component.html
@@ -90,6 +90,7 @@
[igxTemplateOutletContext]="getContext(rowData, rowIndex)"
(cachedViewLoaded)="cachedViewLoaded($event)"
(viewCreated)="viewCreatedHandler($event)"
+ (beforeViewDetach)="viewDetachHandler($event)"
(viewMoved)="viewMovedHandler($event)">
diff --git a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.html b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.html
index 8cd4c1eea35..458067138e9 100644
--- a/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.html
+++ b/projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.html
@@ -68,7 +68,7 @@
+ (viewMoved)="viewMovedHandler($event)" (cachedViewLoaded)="cachedViewLoaded($event)" (beforeViewDetach)="viewDetachHandler($event)">
diff --git a/projects/igniteui-angular/src/lib/grids/row.directive.ts b/projects/igniteui-angular/src/lib/grids/row.directive.ts
index b2118b1f15e..18faef7484b 100644
--- a/projects/igniteui-angular/src/lib/grids/row.directive.ts
+++ b/projects/igniteui-angular/src/lib/grids/row.directive.ts
@@ -458,6 +458,10 @@ export class IgxRowDirective implements DoCheck, AfterViewInit, OnDestroy {
* @internal
*/
public ngOnDestroy() {
+ // if action strip is shown here but row is about to be destroyed, hide it.
+ if (this.grid.actionStrip && this.grid.actionStrip.context === this) {
+ this.grid.actionStrip.hide();
+ }
this.destroy$.next(true);
this.destroy$.complete();
}
diff --git a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.html b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.html
index 17bc02196b6..b82306c2bd3 100644
--- a/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.html
+++ b/projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.html
@@ -71,6 +71,7 @@
(dataChanging)="dataRebinding($event)" (dataChanged)="dataRebound($event)">