diff --git a/CHANGELOG.md b/CHANGELOG.md index 53ca08bf9ec..1160f119d7a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,11 @@ All notable changes for each version of this project will be documented in this - `IgxCombo`, `IgxSimpleCombo` - Combo and Simple Combo now close the dropdown list and move the focus to the next focusable element on "Tab" press and clear the selection if the combo is collapsed on "Escape". +### Behavioral Changes + +- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid` + - Cell Selection is now cleared when changing the expand/collapse state of column grouping, master-detail, tree and hierarchical grids to ensure non-erroneous behavior when underlying indexes are modified. + ### Breaking Changes - `igxForOf`, `igxGrid`, `igxTreeGrid`, `igxHierarchicalGrid`, `igxPivotGrid` diff --git a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts index c0c4279a1b0..2536bb092d6 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-base.directive.ts @@ -4385,6 +4385,7 @@ export abstract class IgxGridBaseDirective implements GridType, public set expansionStates(value) { this._expansionStates = new Map(value); this.expansionStatesChange.emit(this._expansionStates); + this.clearCellSelection(); this.notifyChanges(true); if (this.gridAPI.grid) { this.cdr.detectChanges(); diff --git a/projects/igniteui-angular/grids/grid/src/grid-cell-selection.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-cell-selection.spec.ts index cb622a8250f..aa07659bf5d 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-cell-selection.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-cell-selection.spec.ts @@ -11,7 +11,7 @@ import { } from '../../../test-utils/grid-samples.spec'; import { UIInteractions, wait } from '../../../test-utils/ui-interactions.spec'; import { clearGridSubs, setupGridScrollDetection } from '../../../test-utils/helper-utils.spec'; -import { GridSelectionMode } from 'igniteui-angular/grids/core'; +import { GridSelectionMode, IgxGroupByRow } from 'igniteui-angular/grids/core'; import { GridSelectionFunctions, GridFunctions } from '../../../test-utils/grid-functions.spec'; import { DebugElement } from '@angular/core'; @@ -1739,7 +1739,7 @@ describe('IgxGrid - Cell selection #grid', () => { describe('Features integration', () => { let fix; - let grid; + let grid: IgxGridComponent; let detect; beforeEach(() => { @@ -2298,13 +2298,7 @@ describe('IgxGrid - Cell selection #grid', () => { grid.clearGrouping(); fix.detectChanges(); - const newSelectedData = [ - { ParentID: 147, Name: 'Monica Reyes', HireDate: new Date('Sep 18, 2014') }, - { ParentID: 847, Name: 'Laurence Johnson', HireDate: new Date('May 4, 2014') }, - { ParentID: 847, Name: 'Elizabeth Richards', HireDate: new Date('Dec 9, 2017') } - ]; - GridSelectionFunctions.verifySelectedRange(grid, 2, 4, 1, 3); - expect(grid.getSelectedData()).toEqual(newSelectedData); + expect(grid.getSelectedData().length).toEqual(0, 'Selection should be cleared when grouping is cleared'); }); it('GroupBy: selected range should remain the same when perform grouping ', () => { @@ -2348,16 +2342,10 @@ describe('IgxGrid - Cell selection #grid', () => { ]; GridSelectionFunctions.verifySelectedRange(grid, 2, 4, 1, 3); expect(grid.getSelectedData()).toEqual(selectedData); - grid.rowList.first.toggle(); + (grid.rowList.first as unknown as IgxGroupByRow).toggle(); fix.detectChanges(); - const newSelectedData = [ - { ParentID: 147, Name: 'Michael Langdon', HireDate: new Date('Jul 3, 2011') }, - { ParentID: 147, Name: 'Thomas Hardy', HireDate: new Date('Jul 19, 2009') }, - { ParentID: 147, Name: 'Monica Reyes', HireDate: new Date('Sep 18, 2014') } - ]; - GridSelectionFunctions.verifySelectedRange(grid, 2, 4, 1, 3); - expect(grid.getSelectedData()).toEqual(newSelectedData); + expect(grid.getSelectedData().length).toEqual(0, 'Selection should be cleared when toggling a group row'); }); it('Grouping: selected data should be empty when all group rows are collapsed', () => { @@ -2378,15 +2366,8 @@ describe('IgxGrid - Cell selection #grid', () => { grid.toggleAllGroupRows(); fix.detectChanges(); - GridSelectionFunctions.verifySelectedRange(grid, 2, 4, 1, 3); expect(grid.dataRowList.length).toBe(0); expect(grid.getSelectedData()).toEqual([]); - grid.toggleAllGroupRows(); - fix.detectChanges(); - - expect(grid.dataRowList.lenght).not.toBe(0); - GridSelectionFunctions.verifySelectedRange(grid, 2, 4, 1, 3); - expect(grid.getSelectedData()).toEqual(selectedData); }); it('Moving: selection should not change when move columns inside selected range', fakeAsync(() => { @@ -2552,7 +2533,7 @@ describe('IgxGrid - Cell selection #grid', () => { GridSelectionFunctions.verifySelectedRange(grid, 2, 4, 1, 3); GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 4, 1, 3); expect(grid.getSelectedData()).toEqual(newSelection); - grid.selectRange(); + grid.clearCellSelection(); fix.detectChanges(); const range = { rowStart: 0, rowEnd: 4, columnStart: 'ID', columnEnd: 'OnPTO' }; grid.selectRange(range); diff --git a/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav.spec.ts b/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav.spec.ts index 91b3e06a24e..e153c550836 100644 --- a/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav.spec.ts +++ b/projects/igniteui-angular/grids/grid/src/grid-keyBoardNav.spec.ts @@ -961,7 +961,8 @@ describe('IgxGrid - Keyboard navigation #grid', () => { expect(cell.selected).toBe(true); })); - it('should keep selected cell when expand/collapse grouped row ', (async () => { + /* S.S. Behavioral change from 21.1 - selection is cleared when expand/collapsing due to indexes being unstable */ + xit('should keep selected cell when expand/collapse grouped row ', (async () => { grid.tbody.nativeElement.focus(); fix.detectChanges(); diff --git a/projects/igniteui-angular/grids/grid/src/grid.component.ts b/projects/igniteui-angular/grids/grid/src/grid.component.ts index 83a38112d0b..da2ecaeb7a6 100644 --- a/projects/igniteui-angular/grids/grid/src/grid.component.ts +++ b/projects/igniteui-angular/grids/grid/src/grid.component.ts @@ -550,6 +550,8 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType, } public set groupingExpansionState(value) { + // Index-based selection needs to be cleared + this.clearCellSelection(); if (value !== this._groupingExpandState) { this.groupingExpansionStateChange.emit(value); } @@ -1348,6 +1350,7 @@ export class IgxGridComponent extends IgxGridBaseDirective implements GridType, * @hidden */ protected _toggleGroup(groupRow: IGroupByRecord) { + this.clearCellSelection(); this._gridAPI.groupBy_toggle_group(groupRow); } diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-keyBoardNav.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-keyBoardNav.spec.ts index 1fc344f8240..2ec23241789 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-keyBoardNav.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-keyBoardNav.spec.ts @@ -182,7 +182,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); UIInteractions.triggerEventHandlerKeyDown('ArrowLeft', gridContent, true); fix.detectChanges(); @@ -190,7 +190,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(4); TreeGridFunctions.verifyTreeRowHasCollapsedIcon(rows[0]); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); expect(treeGrid.rowToggle.emit).toHaveBeenCalledTimes(1); UIInteractions.triggerEventHandlerKeyDown('ArrowLeft', gridContent, true); @@ -199,7 +199,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(4); TreeGridFunctions.verifyTreeRowHasCollapsedIcon(rows[0]); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); expect(treeGrid.rowToggle.emit).toHaveBeenCalledTimes(1); UIInteractions.triggerEventHandlerKeyDown('ArrowRight', gridContent, true); @@ -208,7 +208,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(10); TreeGridFunctions.verifyTreeRowHasExpandedIcon(rows[0]); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); expect(treeGrid.rowToggle.emit).toHaveBeenCalledTimes(2); UIInteractions.triggerEventHandlerKeyDown('ArrowRight', gridContent, true); @@ -217,7 +217,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(10); TreeGridFunctions.verifyTreeRowHasExpandedIcon(rows[0]); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); expect(treeGrid.rowToggle.emit).toHaveBeenCalledTimes(2); }); @@ -230,7 +230,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { UIInteractions.simulateClickAndSelectEvent(cell); fix.detectChanges(); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); UIInteractions.triggerEventHandlerKeyDown('ArrowUp', gridContent, true); fix.detectChanges(); @@ -238,7 +238,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(7); TreeGridFunctions.verifyTreeRowHasCollapsedIcon(rows[3]); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); expect(treeGrid.rowToggle.emit).toHaveBeenCalledTimes(1); UIInteractions.triggerEventHandlerKeyDown('ArrowUp', gridContent, true); @@ -247,7 +247,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(7); TreeGridFunctions.verifyTreeRowHasCollapsedIcon(rows[3]); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); expect(treeGrid.rowToggle.emit).toHaveBeenCalledTimes(1); UIInteractions.triggerEventHandlerKeyDown('ArrowDown', gridContent, true); @@ -256,7 +256,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(10); TreeGridFunctions.verifyTreeRowHasExpandedIcon(rows[3]); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); expect(treeGrid.rowToggle.emit).toHaveBeenCalledTimes(2); UIInteractions.triggerEventHandlerKeyDown('ArrowDown', gridContent, true); @@ -265,7 +265,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(10); TreeGridFunctions.verifyTreeRowHasExpandedIcon(rows[3]); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); expect(treeGrid.rowToggle.emit).toHaveBeenCalledTimes(2); }); @@ -598,7 +598,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { await wait(DEBOUNCETIME); fix.detectChanges(); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); let rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(7); TreeGridFunctions.verifyTreeRowHasCollapsedIcon(rows[3]); @@ -607,7 +607,7 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { await wait(DEBOUNCETIME); fix.detectChanges(); - TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); + // TreeGridFunctions.verifyTreeGridCellSelected(treeGrid, cell); rows = TreeGridFunctions.getAllRows(fix); expect(rows.length).toBe(8); TreeGridFunctions.verifyTreeRowHasExpandedIcon(rows[3]); @@ -767,7 +767,9 @@ describe('IgxTreeGrid - Key Board Navigation #tGrid', () => { expect(treeGrid.headerContainer.getScroll().scrollLeft).toEqual(scrollLeft); }); - it('should select correct cells after expand/collapse row', async () => { + /* S.S. The test is now redundant as it covers the same scenario as a previous one just also including scrolls, which + no longer change anything because of the behavioral change that clears selection on expand/collapse. */ + xit('should select correct cells after expand/collapse row', async () => { // Select first cell and expand collapse let rows; let cell = treeGrid.gridAPI.get_cell_by_index(0, 'ID'); diff --git a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-multi-cell-selection.spec.ts b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-multi-cell-selection.spec.ts index 261edf9ce2e..6693bf2cbcb 100644 --- a/projects/igniteui-angular/grids/tree-grid/src/tree-grid-multi-cell-selection.spec.ts +++ b/projects/igniteui-angular/grids/tree-grid/src/tree-grid-multi-cell-selection.spec.ts @@ -132,7 +132,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { expect(treeGrid.getSelectedData()).toEqual([{ ID: 957 }]); }); - it('Should not change selection when expand collapse row with keyboard', (async () => { + it('Should clear selection when expand collapse row with keyboard', (async () => { const expectedData1 = [ { ID: 19 }, { ID: 15 } @@ -157,20 +157,7 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { UIInteractions.triggerKeyDownEvtUponElem('arrowleft', startCell.nativeElement, true, true); await wait(30); fix.detectChanges(); - - GridSelectionFunctions.verifyCellsRegionSelected(treeGrid, 10, 11, 0, 0); - GridSelectionFunctions.verifySelectedRange(treeGrid, 10, 11, 0, 0); - expect(treeGrid.getSelectedData()).toEqual(expectedData2); - - startCell = treeGrid.gridAPI.get_cell_by_index(10, 'ID'); - UIInteractions.triggerKeyDownEvtUponElem('arrowright', startCell.nativeElement, true, true); - await wait(30); - fix.detectChanges(); - - startCell = treeGrid.gridAPI.get_cell_by_index(10, 'ID'); - GridSelectionFunctions.verifyCellsRegionSelected(treeGrid, 10, 11, 0, 0); - GridSelectionFunctions.verifySelectedRange(treeGrid, 10, 11, 0, 0); - expect(treeGrid.getSelectedData()).toEqual(expectedData1); + expect(treeGrid.getSelectedData().length).toEqual(0, 'Expand/collapsing a tree grid row with keyboard should clear cell selection'); })); it('Should be able to select a range with holding Shift key', (async () => { @@ -997,29 +984,6 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { { ID: 998, Name: 'Sven Ottlieb', Age: 44 }, { ID: 847, Name: 'Ana Sanders', Age: 42 } ]; - const expectedData2 = [ - { ID: 475, Name: 'Michael Langdon', Age: 43 }, - { ID: 957, Name: 'Thomas Hardy', Age: 29 }, - { ID: 317, Name: 'Monica Reyes', Age: 31 }, - { ID: 847, Name: 'Ana Sanders', Age: 42 }, - { ID: 225, Name: 'Laurence Johnson', Age: 44 }, - { ID: 663, Name: 'Elizabeth Richards', Age: 25 } - ]; - - const expectedData3 = [ - { ID: 847, Name: 'Ana Sanders', Age: 42 }, - { ID: 225, Name: 'Laurence Johnson', Age: 44 }, - { ID: 663, Name: 'Elizabeth Richards', Age: 25 }, - { ID: 141, Name: 'Trevor Ashworth', Age: 39 }, - { ID: 19, Name: 'Victoria Lincoln', Age: 49 }, - { ID: 15, Name: 'Antonio Moreno', Age: 44 } - ]; - - const expectedData4 = [ - { ID: 847, Name: 'Ana Sanders', Age: 42 }, - { ID: 19, Name: 'Victoria Lincoln', Age: 49 }, - { ID: 17, Name: 'Yang Wang', Age: 61 } - ]; treeGrid.selectRange(range); fix.detectChanges(); @@ -1031,30 +995,15 @@ describe('IgxTreeGrid - Multi Cell selection #tGrid', () => { treeGrid.toggleRow(treeGrid.getRowByIndex(3).key); fix.detectChanges(); - GridSelectionFunctions.verifyCellsRegionSelected(treeGrid, 1, 6, 0, 2); - GridSelectionFunctions.verifySelectedRange(treeGrid, 1, 6, 0, 2); - expect(treeGrid.getSelectedData()).toEqual(expectedData2); + expect(treeGrid.getSelectedData().length).toBe(0, 'Expand/collapsing a tree grid row should clear cell selection'); - treeGrid.toggleRow(treeGrid.getRowByIndex(0).key); + treeGrid.selectRange(range); fix.detectChanges(); - GridSelectionFunctions.verifyCellsRegionSelected(treeGrid, 1, 6, 0, 2); - GridSelectionFunctions.verifySelectedRange(treeGrid, 1, 6, 0, 2); - expect(treeGrid.getSelectedData()).toEqual(expectedData3); - treeGrid.collapseAll(); fix.detectChanges(); - GridSelectionFunctions.verifyCellsRegionSelected(treeGrid, 1, 3, 0, 2); - GridSelectionFunctions.verifySelectedRange(treeGrid, 1, 6, 0, 2); - expect(treeGrid.getSelectedData()).toEqual(expectedData4); - - treeGrid.expandAll(); - fix.detectChanges(); - - GridSelectionFunctions.verifyCellsRegionSelected(treeGrid, 1, 6, 0, 2); - GridSelectionFunctions.verifySelectedRange(treeGrid, 1, 6, 0, 2); - expect(treeGrid.getSelectedData()).toEqual(expectedData1); + expect(treeGrid.getSelectedData().length).toBe(0, 'Expand/collapsing all tree rows should clear cell selection'); }; const verifySelectingRangeWithMouseDrag = (fix, treeGrid, detect) => {