Skip to content

Commit 2f82308

Browse files
authored
fix(action-strip): Assign parent to not destroy on DOM move. (#15940)
1 parent ba08fdc commit 2f82308

File tree

9 files changed

+134
-2
lines changed

9 files changed

+134
-2
lines changed

projects/igniteui-angular-elements/src/app/custom-strategy.spec.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ import {
1111
IgcColumnComponent,
1212
IgcPaginatorComponent,
1313
IgcGridStateComponent,
14+
IgcColumnLayoutComponent,
15+
IgcActionStripComponent,
16+
IgcGridEditingActionsComponent,
1417
} from './components';
1518
import { defineComponents } from '../utils/register';
1619

@@ -25,6 +28,8 @@ describe('Elements: ', () => {
2528
IgcColumnComponent,
2629
IgcPaginatorComponent,
2730
IgcGridStateComponent,
31+
IgcActionStripComponent,
32+
IgcGridEditingActionsComponent
2833
);
2934
});
3035

@@ -181,5 +186,66 @@ describe('Elements: ', () => {
181186
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 2));
182187
expect(() => stateComponent.getStateAsString()).not.toThrow();
183188
});
189+
190+
it('should not destroy action strip when row it is shown in is destroyed or cached.', async() => {
191+
const innerHtml = `
192+
<igc-grid id="testGrid" auto-generate>
193+
<igc-action-strip id="testStrip">
194+
<igc-grid-editing-actions add-row="true"></igc-grid-editing-actions>
195+
</igc-action-strip>
196+
</igc-grid>`;
197+
testContainer.innerHTML = innerHtml;
198+
199+
// TODO: Better way to wait - potentially expose the queue or observable for update on the strategy
200+
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
201+
202+
const grid = document.querySelector<IgcNgElement & InstanceType<typeof IgcGridComponent>>('#testGrid');
203+
const actionStrip = document.querySelector<IgcNgElement & InstanceType<typeof IgcActionStripComponent>>('#testStrip');
204+
grid.data = SampleTestData.foodProductData();
205+
206+
// TODO: Better way to wait - potentially expose the queue or observable for update on the strategy
207+
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
208+
209+
let row = grid.dataRowList.toArray()[0];
210+
actionStrip.show(row);
211+
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
212+
213+
expect(actionStrip.hidden).toBeFalse();
214+
215+
grid.data = [];
216+
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
217+
218+
// row destroyed
219+
expect((row.cdr as any).destroyed).toBeTrue();
220+
// action strip still in DOM, only hidden.
221+
expect(actionStrip.hidden).toBeTrue();
222+
expect(actionStrip.isConnected).toBeTrue();
223+
224+
grid.data = SampleTestData.foodProductData();
225+
grid.groupBy({ fieldName: 'InStock', dir: 1, ignoreCase: false });
226+
227+
// TODO: Better way to wait - potentially expose the queue or observable for update on the strategy
228+
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
229+
230+
row = grid.dataRowList.toArray()[0];
231+
actionStrip.show(row);
232+
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
233+
234+
expect(actionStrip.hidden).toBeFalse();
235+
236+
// collapse all data rows, leave only groups
237+
grid.toggleAllGroupRows();
238+
239+
// TODO: Better way to wait - potentially expose the queue or observable for update on the strategy
240+
await firstValueFrom(timer(10 /* SCHEDULE_DELAY */ * 3));
241+
242+
// row not destroyed, but also not in dom anymore
243+
expect((row.cdr as any).destroyed).toBeFalse();
244+
expect(row.element.nativeElement.isConnected).toBe(false);
245+
246+
// action strip still in DOM, only hidden.
247+
expect(actionStrip.hidden).toBeTrue();
248+
expect(actionStrip.isConnected).toBeTrue();
249+
});
184250
});
185251
});

projects/igniteui-angular-elements/src/app/custom-strategy.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ class IgxCustomNgElementStrategy extends ComponentNgElementStrategy {
126126
parentComponentRef = await parent?.ngElementStrategy[ComponentRefKey];
127127
parentAnchor = parentComponentRef?.instance.anchor;
128128
}
129+
129130
} else if ((parent as any)?.__componentRef) {
130131
this.angularParent = (parent as any).__componentRef;
131132
parentInjector = this.angularParent.injector;

projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.spec.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { IgxGridPinningActionsComponent } from './grid-pinning-actions.component
1515
import { IgxActionStripComponent } from '../action-strip.component';
1616
import { IRowDataCancelableEventArgs, IgxColumnComponent } from '../../grids/public_api';
1717
import { SampleTestData } from '../../test-utils/sample-test-data.spec';
18+
import { SortingDirection } from '../../data-operations/sorting-strategy';
1819

1920
describe('igxGridEditingActions #grid ', () => {
2021
let fixture;
@@ -274,6 +275,59 @@ describe('igxGridEditingActions #grid ', () => {
274275

275276
expect(actionStrip.hidden).toBeTrue();
276277
});
278+
279+
it('should auto-hide on delete action click.', () => {
280+
const row = grid.rowList.toArray()[0];
281+
actionStrip.show(row);
282+
fixture.detectChanges();
283+
284+
expect(actionStrip.hidden).toBeFalse();
285+
286+
const deleteIcon = fixture.debugElement.queryAll(By.css(`igx-grid-editing-actions igx-icon`))[1];
287+
expect(deleteIcon.nativeElement.innerText).toBe('delete');
288+
deleteIcon.parent.triggerEventHandler('click', new Event('click'));
289+
fixture.detectChanges();
290+
291+
expect(actionStrip.hidden).toBeTrue();
292+
293+
});
294+
295+
it('should auto-hide if context row is destroyed.', () => {
296+
const row = grid.rowList.toArray()[0];
297+
actionStrip.show(row);
298+
fixture.detectChanges();
299+
300+
expect(actionStrip.hidden).toBeFalse();
301+
302+
// bind to no data, which removes all rows.
303+
grid.data = [];
304+
grid.cdr.detectChanges();
305+
306+
expect((row.cdr as any).destroyed).toBeTrue();
307+
expect(actionStrip.hidden).toBeTrue();
308+
});
309+
310+
it('should auto-hide if context row is cached.', () => {
311+
// create group rows
312+
grid.groupBy({ fieldName: 'ContactTitle', dir: SortingDirection.Desc, ignoreCase: false });
313+
fixture.detectChanges();
314+
315+
// show for first data row
316+
const row = grid.dataRowList.toArray()[0];
317+
actionStrip.show(row);
318+
fixture.detectChanges();
319+
320+
// collapse all groups to cache data rows
321+
grid.toggleAllGroupRows();
322+
fixture.detectChanges();
323+
324+
// not destroyed, but not in DOM anymore
325+
expect((row.cdr as any).destroyed).toBeFalse();
326+
expect(row.element.nativeElement.isConnected).toBe(false);
327+
328+
// action strip should be hidden
329+
expect(actionStrip.hidden).toBeTrue();
330+
});
277331
});
278332

279333
describe('auto show/hide in HierarchicalGrid', () => {

projects/igniteui-angular/src/lib/action-strip/grid-actions/grid-editing-actions.component.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,6 @@ export class IgxGridEditingActionsComponent extends IgxGridActionsBaseDirective
147147
const context = this.strip.context;
148148
const grid = context.grid;
149149
grid.deleteRow(context.key);
150-
151150
this.strip.hide();
152151
}
153152

projects/igniteui-angular/src/lib/grids/grid-base.directive.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6205,6 +6205,12 @@ export abstract class IgxGridBaseDirective implements GridType,
62056205
}
62066206
}
62076207

6208+
protected viewDetachHandler(args) {
6209+
if (this.actionStrip && args.view.rootNodes.find(x => x === this.actionStrip.context?.element.nativeElement)) {
6210+
this.actionStrip.hide();
6211+
}
6212+
}
6213+
62086214
/**
62096215
* @hidden @internal
62106216
*/

projects/igniteui-angular/src/lib/grids/grid/grid.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@
9090
[igxTemplateOutletContext]="getContext(rowData, rowIndex)"
9191
(cachedViewLoaded)="cachedViewLoaded($event)"
9292
(viewCreated)="viewCreatedHandler($event)"
93+
(beforeViewDetach)="viewDetachHandler($event)"
9394
(viewMoved)="viewMovedHandler($event)">
9495
</ng-template>
9596
</ng-template>

projects/igniteui-angular/src/lib/grids/hierarchical-grid/hierarchical-grid.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
<ng-template
6969
[igxTemplateOutlet]="(isHierarchicalRecord(rowData) ? hierarchical_record_template : (isChildGridRecord(rowData) ? child_record_template : hierarchical_record_template))"
7070
[igxTemplateOutletContext]="getContext(rowData, rowIndex, false)" (viewCreated)="viewCreatedHandler($event)"
71-
(viewMoved)="viewMovedHandler($event)" (cachedViewLoaded)="cachedViewLoaded($event)">
71+
(viewMoved)="viewMovedHandler($event)" (cachedViewLoaded)="cachedViewLoaded($event)" (beforeViewDetach)="viewDetachHandler($event)">
7272
</ng-template>
7373
<!-- <ng-container *igxTemplateOutlet="(isHierarchicalRecord(rowData) ? hierarchical_record_template : (isChildGridRecord(rowData) && isExpanded(rowData) ? child_record_template : hierarchical_record_template)); context: getContext(rowData)"></ng-container> -->
7474
</ng-template>

projects/igniteui-angular/src/lib/grids/row.directive.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,10 @@ export class IgxRowDirective implements DoCheck, AfterViewInit, OnDestroy {
458458
* @internal
459459
*/
460460
public ngOnDestroy() {
461+
// if action strip is shown here but row is about to be destroyed, hide it.
462+
if (this.grid.actionStrip && this.grid.actionStrip.context === this) {
463+
this.grid.actionStrip.hide();
464+
}
461465
this.destroy$.next(true);
462466
this.destroy$.complete();
463467
}

projects/igniteui-angular/src/lib/grids/tree-grid/tree-grid.component.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@
7171
(dataChanging)="dataRebinding($event)" (dataChanged)="dataRebound($event)">
7272
<ng-template [igxTemplateOutlet]='isSummaryRow(rowData) ? summary_template : record_template'
7373
[igxTemplateOutletContext]='getContext(rowData, rowIndex, false)'
74+
(beforeViewDetach)="viewDetachHandler($event)"
7475
(cachedViewLoaded)='cachedViewLoaded($event)'>
7576
</ng-template>
7677
</ng-template>

0 commit comments

Comments
 (0)