Skip to content

Commit e492fab

Browse files
authored
Merge pull request #12621 from IgniteUI/mkirkova/feat-12522
Deselect cell with ctrl + click
2 parents 20adbab + 7eaa571 commit e492fab

File tree

5 files changed

+75
-13
lines changed

5 files changed

+75
-13
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ All notable changes for each version of this project will be documented in this
2424

2525
- `IgxGrid`
2626
- Added new auto-sizing API `recalculateAutoSizes` that recalculates widths of columns that have size set to `auto`. Can be used in scenarios where you want to auto-size the columns again post initialization.
27+
- Clicking with the Left Mouse key while holding `Ctrl` on selected cell will deselect the cell.
2728
- `igxPivotGrid`
2829
- Adding `aggregatorName` for pivot value configuration as an alternative to setting `aggregator` function. If both are set `aggregatorName` takes precedent. If none are set an error is thrown.
2930
- `IgxSimpleCombo`

projects/igniteui-angular/src/lib/grids/cell.component.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -973,6 +973,8 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy, CellT
973973
this.grid.crudService.updateCell(true, event);
974974
}
975975
return;
976+
} else {
977+
this.selectionService.primaryButton = true;
976978
}
977979
this.selectionService.pointerDown(this.selectionNode, event.shiftKey, event.ctrlKey);
978980
this.activate(event);
@@ -1030,11 +1032,16 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy, CellT
10301032
*/
10311033
public activate(event: FocusEvent | KeyboardEvent) {
10321034
const node = this.selectionNode;
1033-
const shouldEmitSelection = !this.selectionService.isActiveNode(node);
1034-
1035+
let shouldEmitSelection = !this.selectionService.isActiveNode(node);
1036+
10351037
if (this.selectionService.primaryButton) {
10361038
const currentActive = this.selectionService.activeElement;
1037-
this.selectionService.activeElement = node;
1039+
if (this.cellSelectionMode === GridSelectionMode.single && (event as any)?.ctrlKey && this.selected) {
1040+
this.selectionService.activeElement = null;
1041+
shouldEmitSelection = true;
1042+
} else {
1043+
this.selectionService.activeElement = node;
1044+
}
10381045
const cancel = this._updateCRUDStatus(event);
10391046
if (cancel) {
10401047
this.selectionService.activeElement = currentActive;
@@ -1066,8 +1073,13 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy, CellT
10661073
}
10671074
this.selectionService.primaryButton = true;
10681075
if (this.cellSelectionMode === GridSelectionMode.multiple && this.selectionService.activeElement) {
1069-
this.selectionService.add(this.selectionService.activeElement, false); // pointer events handle range generation
1070-
this.selectionService.keyboardStateOnFocus(node, this.grid.rangeSelected, this.nativeElement);
1076+
if (this.selectionService.isInMap(this.selectionService.activeElement) && (event as any)?.ctrlKey && !(event as any)?.shiftKey) {
1077+
this.selectionService.remove(this.selectionService.activeElement);
1078+
shouldEmitSelection = true;
1079+
} else {
1080+
this.selectionService.add(this.selectionService.activeElement, false); // pointer events handle range generation
1081+
this.selectionService.keyboardStateOnFocus(node, this.grid.rangeSelected, this.nativeElement);
1082+
}
10711083
}
10721084
if (this.grid.isCellSelectable && shouldEmitSelection) {
10731085
this.zone.run(() => this.grid.selected.emit({ cell: this.getCellType(), event }));

projects/igniteui-angular/src/lib/grids/grid-navigation.service.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,6 +148,9 @@ export class IgxGridNavigationService {
148148
this.grid.cdr.detectChanges();
149149
});
150150
} else {
151+
if (hasLastActiveNode && !this.grid.selectionService.selected(this.lastActiveNode)) {
152+
return;
153+
}
151154
const range = {
152155
rowStart: this.activeNode.row, rowEnd: this.activeNode.row,
153156
columnStart: this.activeNode.column, columnEnd: this.activeNode.column

projects/igniteui-angular/src/lib/grids/grid/grid-cell-selection.spec.ts

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,34 @@ describe('IgxGrid - Cell selection #grid', () => {
225225
GridSelectionFunctions.verifySelectedRange(grid, 0, 0, 0, 0, 2, 3);
226226
});
227227

228+
it('Should be able to select cells correctly when focus is returned to the grid', async() => {
229+
const firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
230+
const secondCell = grid.gridAPI.get_cell_by_index(2, 'Name');
231+
232+
UIInteractions.simulateClickAndSelectEvent(firstCell);
233+
fix.detectChanges();
234+
235+
GridSelectionFunctions.verifyCellSelected(firstCell);
236+
expect(grid.selectedCells.length).toBe(1);
237+
238+
UIInteractions.simulateClickAndSelectEvent(firstCell, false, true);
239+
fix.detectChanges();
240+
241+
expect(grid.selectedCells.length).toBe(0);
242+
243+
grid.navigation.lastActiveNode = grid.navigation.activeNode;
244+
grid.navigation.activeNode = null;
245+
fix.detectChanges();
246+
grid.tbody.nativeElement.focus();
247+
fix.detectChanges();
248+
249+
UIInteractions.simulateClickAndSelectEvent(secondCell, false, true);
250+
fix.detectChanges();
251+
GridSelectionFunctions.verifyCellSelected(firstCell, false);
252+
GridSelectionFunctions.verifyCellSelected(secondCell, true);
253+
expect(grid.selectedCells.length).toBe(1);
254+
});
255+
228256
it('Should be able to select range when click on a cell and hold Shift key and click on another Cell', () => {
229257
const firstCell = grid.gridAPI.get_cell_by_index(3, 'HireDate');
230258
const secondCell = grid.gridAPI.get_cell_by_index(1, 'ID');
@@ -341,7 +369,7 @@ describe('IgxGrid - Cell selection #grid', () => {
341369
];
342370
const expectedData2 = [
343371
{ ID: 475, ParentID: 147, Name: 'Michael Langdon' },
344-
{ ID: 957, ParentID: 147 },
372+
{ ID: 957 },
345373
{ ID: 317, ParentID: 147 }
346374
];
347375

@@ -362,18 +390,17 @@ describe('IgxGrid - Cell selection #grid', () => {
362390
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 2, 0, 1);
363391
GridSelectionFunctions.verifyCellSelected(thirdCell);
364392

365-
// Click on a cell in the region and verify it is not changed
393+
// Click on a cell in the region and verify it is deselected
366394
let cell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
367395
UIInteractions.simulateClickAndSelectEvent(cell, false, true);
368396
fix.detectChanges();
369397

370-
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 2, 0, 1);
371-
GridSelectionFunctions.verifyCellSelected(thirdCell);
398+
GridSelectionFunctions.verifyCellsRegionSelected(grid, 0, 0, 0, 2);
399+
GridSelectionFunctions.verifyCellsRegionSelected(grid, 2, 2, 0, 1);
400+
GridSelectionFunctions.verifyCellSelected(cell, false);
401+
GridSelectionFunctions.verifyCellSelected(grid.gridAPI.get_cell_by_index(1, 'ID'), true);
372402
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
373403
expect(grid.getSelectedData()).toEqual(expectedData2);
374-
GridSelectionFunctions.verifySelectedRange(grid, 0, 2, 0, 1, 0, 3);
375-
GridSelectionFunctions.verifySelectedRange(grid, 0, 0, 2, 2, 1, 3);
376-
GridSelectionFunctions.verifySelectedRange(grid, 1, 1, 1, 1, 2, 3);
377404

378405
// Click on a cell without holding Ctrl
379406
cell = grid.gridAPI.get_cell_by_index(0, 'ID');
@@ -3155,6 +3182,25 @@ describe('IgxGrid - Cell selection #grid', () => {
31553182
GridSelectionFunctions.verifySelectedRange(grid, 0, 0, 0, 0);
31563183
});
31573184

3185+
it('Should deselect a selected cell with Ctrl + click', () => {
3186+
const selectionChangeSpy = spyOn<any>(grid.selected, 'emit').and.callThrough();
3187+
const firstCell = grid.gridAPI.get_cell_by_index(1, 'ParentID');
3188+
3189+
// Click on a cell
3190+
UIInteractions.simulateClickAndSelectEvent(firstCell);
3191+
fix.detectChanges();
3192+
GridSelectionFunctions.verifyCellSelected(firstCell);
3193+
expect(grid.selectedCells.length).toBe(1);
3194+
expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
3195+
3196+
// Click on same cell holding Ctrl
3197+
UIInteractions.simulateClickAndSelectEvent(firstCell, false, true);
3198+
fix.detectChanges();
3199+
GridSelectionFunctions.verifyCellSelected(firstCell, false);
3200+
expect(grid.selectedCells.length).toBe(0);
3201+
expect(selectionChangeSpy).toHaveBeenCalledTimes(2);
3202+
});
3203+
31583204
it('When when navigate with arrow keys cell selection should be changed', () => {
31593205
const selectionChangeSpy = spyOn<any>(grid.selected, 'emit').and.callThrough();
31603206
let cell = grid.gridAPI.get_cell_by_index(1, 'Name');

projects/igniteui-angular/src/lib/grids/selection/selection.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ export class IgxGridSelectionService {
336336
return true;
337337
}
338338

339-
if (this.pointerEventInGridBody) {
339+
if (this.pointerEventInGridBody && this.isActiveNode(node)) {
340340
this.add(node);
341341
}
342342
return false;

0 commit comments

Comments
 (0)