Skip to content

Commit

Permalink
fix(igx-grid): Integration with CRUD behavior
Browse files Browse the repository at this point in the history
Closes #4878
  • Loading branch information
rkaraivanov committed Jun 5, 2019
1 parent e57010c commit 54fcb72
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 58 deletions.
67 changes: 42 additions & 25 deletions projects/igniteui-angular/src/lib/core/grid-selection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,7 @@ export class IgxGridSelectionService {
selection = new Map<number, Set<number>>();
temp = new Map<number, Set<number>>();
_ranges: Set<string> = new Set<string>();
_selectionRange: Range;


/**
Expand All @@ -206,9 +207,7 @@ export class IgxGridSelectionService {
get ranges(): GridSelectionRange[] {

// The last action was keyboard + shift selection -> add it
if (this.keyboardState.range) {
this._ranges.add(JSON.stringify(this.keyboardState.range));
}
this.addKeyboardRange();

const ranges = Array.from(this._ranges).map(range => JSON.parse(range));

Expand Down Expand Up @@ -265,6 +264,15 @@ export class IgxGridSelectionService {
this._ranges.add(JSON.stringify(this.generateRange(node)));
}

/**
* Adds the active keyboard range selection (if any) to the `ranges` meta.
*/
addKeyboardRange(): void {
if (this.keyboardState.range) {
this._ranges.add(JSON.stringify(this.keyboardState.range));
}
}

remove(node: ISelectionNode): void {
if (this.selection.has(node.row)) {
this.selection.get(node.row).delete(node.column);
Expand Down Expand Up @@ -326,7 +334,7 @@ export class IgxGridSelectionService {
/**
*
*/
keyboardStateOnKeydown(node: ISelectionNode, shift: boolean, shiftTab: boolean) {
keyboardStateOnKeydown(node: ISelectionNode, shift: boolean, shiftTab: boolean): void {
this.keyboardState.active = true;
this.initPointerState();
this.keyboardState.shift = shift && !shiftTab;
Expand Down Expand Up @@ -360,10 +368,7 @@ export class IgxGridSelectionService {

pointerDown(node: ISelectionNode, shift: boolean, ctrl: boolean): void {

if (this.keyboardState.range) {
this._ranges.add(JSON.stringify(this.keyboardState.range));
}

this.addKeyboardRange();
this.initKeyboardState();
this.pointerState.ctrl = ctrl;
this.pointerState.shift = shift;
Expand All @@ -376,7 +381,7 @@ export class IgxGridSelectionService {
if (shift) {
// No previously 'clicked' node. Use the last active node.
if (!this.pointerState.node) {
this.pointerState.node = this.activeElement;
this.pointerState.node = this.activeElement || node;
}
this.pointerDownShiftKey(node);
this.clearTextSelection();
Expand Down Expand Up @@ -426,13 +431,14 @@ export class IgxGridSelectionService {
this.pointerState.node = node;
}

this.pointerState.ctrl ? this.blah(node, this.pointerState) :
this.pointerState.ctrl ? this.selectRange(node, this.pointerState, this.temp) :
this.dragSelect(node, this.pointerState);
return true;
}

pointerUp(node: ISelectionNode, emitter: EventEmitter<GridSelectionRange>): boolean {
if (this.dragMode) {
this.restoreTextSelection();
this.addRangeMeta(node, this.pointerState);
this.mergeMap(this.selection, this.temp);
this.zone.runTask(() => emitter.emit(this.generateRange(node, this.pointerState)));
Expand All @@ -443,6 +449,7 @@ export class IgxGridSelectionService {

if (this.pointerState.shift) {
this.clearTextSelection();
this.restoreTextSelection();
emitter.emit(this.generateRange(node, this.pointerState));
this.addRangeMeta(node, this.pointerState);
return true;
Expand All @@ -452,23 +459,15 @@ export class IgxGridSelectionService {
return false;
}

selectRange(node: ISelectionNode, state: SelectionState) {
const { rowStart, rowEnd, columnStart, columnEnd } = this.generateRange(node, state);
for (let i = rowStart; i <= rowEnd; i++) {
for (let j = columnStart as number; j <= columnEnd; j++) {
this.selection.has(i) ? this.selection.get(i).add(j) :
this.selection.set(i, new Set<number>()).get(i).add(j);
}
selectRange(node: ISelectionNode, state: SelectionState, collection: Map<number, Set<number>> = this.selection): void {
if (collection === this.temp) {
collection.clear();
}
}

blah(node: ISelectionNode, state: SelectionState) {
this.temp.clear();
const { rowStart, rowEnd, columnStart, columnEnd } = this.generateRange(node, state);
for (let i = rowStart; i <= rowEnd; i++) {
for (let j = columnStart as number; j <= columnEnd; j++) {
this.temp.has(i) ? this.temp.get(i).add(j) :
this.temp.set(i, new Set<number>()).get(i).add(j);
collection.has(i) ? collection.get(i).add(j) :
collection.set(i, new Set<number>()).get(i).add(j);
}
}
}
Expand All @@ -486,10 +485,28 @@ export class IgxGridSelectionService {
this._ranges.clear();
}

clearTextSelection() {
clearTextSelection(): void {
const selection = window.getSelection();
if (selection) {
if (selection.rangeCount) {
this._selectionRange = selection.getRangeAt(0);
this._selectionRange.collapse(true);
selection.removeAllRanges();
}
}

restoreTextSelection(): void {
const selection = window.getSelection();
if (!selection.rangeCount) {
selection.addRange(this._selectionRange);
}
}

_moveSelectionChrome(node: Node) {
const selection = window.getSelection();
selection.removeAllRanges();
const range = new Range();
range.selectNode(node);
range.collapse(true);
selection.addRange(range);
}
}
2 changes: 1 addition & 1 deletion projects/igniteui-angular/src/lib/core/utils.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/**
*@hidden
*/
export function cloneArray(array, deep?: boolean) {
export function cloneArray(array: any[], deep?: boolean) {
const arr = [];
if (!array) {
return arr;
Expand Down
43 changes: 33 additions & 10 deletions projects/igniteui-angular/src/lib/grids/cell.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -569,12 +569,24 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
* @internal
*/
_updateCRUDStatus() {
if (this.editable && this.crudService.inEditMode && !this.row.deleted) {
this.gridAPI.update_cell(this.crudService.cell, this.crudService.cell.editValue);
this.crudService.end();
const crud = this.crudService;
const editableCell = this.crudService.cell;
const editMode = !!(crud.row || crud.cell);


if (this.editable && editMode && !this.row.deleted) {
if (editableCell) {
this.gridAPI.update_cell(editableCell, editableCell.editValue);
}
crud.end();
this.grid.cdr.markForCheck();
this.crudService.begin(this);
} else if (this.crudService.inEditMode) {
crud.begin(this);
return;
}

if (editableCell && crud.sameRow(this.cellID.rowID)) {
this.gridAPI.submit_value();
} else if (editMode && !crud.sameRow(this.cellID.rowID)) {
this.grid.endEdit(true);
}
}
Expand All @@ -589,7 +601,6 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
}

const node = this.selectionNode;

this._updateCRUDStatus();
this.selectionService.keyboardStateOnFocus(node, this.grid.onRangeSelection);
}
Expand Down Expand Up @@ -669,6 +680,8 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
*/
pointerdown = (event: PointerEvent) => {
if (!isLeftClick(event)) {
this.selectionService.addKeyboardRange();
this.selectionService.initKeyboardState();
this.selectionService.primaryButton = false;
return;
}
Expand Down Expand Up @@ -745,14 +758,23 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
*/
@HostListener('focus', ['$event'])
public onFocus(event: FocusEvent) {
const node = this.selectionNode;

this.focused = true;
this.row.focused = true;
this._updateCellSelectionStatus();
if (!this.selectionService.isActiveNode(this.selectionNode)) {

if (!this.selectionService.isActiveNode(node) && !this.editMode) {
this.grid.onSelection.emit({ cell: this, event });
}

if (this.selectionService.primaryButton) {
this.selectionService.activeElement = this.selectionNode;
this._updateCellSelectionStatus();
this.selectionService.activeElement = node;
} else {
this.selectionService.activeElement = null;
if (this.crudService.inEditMode && !this.editMode) {
this.gridAPI.submit_value();
}
}
this.selectionService.primaryButton = true;
}
Expand Down Expand Up @@ -824,7 +846,8 @@ export class IgxGridCellComponent implements OnInit, OnChanges, OnDestroy {
const keydownArgs = { targetType: 'dataCell', target: this, event: event, cancel: false };
this.grid.onGridKeydown.emit(keydownArgs);
if (keydownArgs.cancel) {
this.selectionService.keyboardStateOnKeydown(node, shift, shift && key === 'tab');
this.selectionService.clear();
this.selectionService.keyboardState.active = true;
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,18 +97,14 @@ describe('IgxGrid - Multi Cell selection', () => {

// Simulate right-click
const endCell = grid.getCellByColumn(4, 'ID');
endCell.nativeElement.dispatchEvent(new PointerEvent('pointerdown', { button: 2 }));
endCell.nativeElement.dispatchEvent(new Event('focus'));
endCell.nativeElement.dispatchEvent(new PointerEvent('pointerup', { button: 2 }));
UIInteractions.simulateNonPrimaryClick(endCell);
detect();

HelperUtils.verifySelectedRange(grid, 2, 3, 0, 1, 0, 1);
expect(selectionChangeSpy).toHaveBeenCalledTimes(0);

const c = grid.getCellByColumn(0, 'ID');
c.nativeElement.dispatchEvent(new PointerEvent('pointerdown'));
c.nativeElement.dispatchEvent(new Event('focus'));
c.nativeElement.dispatchEvent(new PointerEvent('pointerup'));
UIInteractions.simulateClickAndSelectCellEvent(c);
detect();

expect(selectionChangeSpy).toHaveBeenCalledTimes(0);
Expand Down Expand Up @@ -817,6 +813,35 @@ describe('IgxGrid - Multi Cell selection', () => {
expect(grid.getSelectedData()).toEqual([{ID: 957, ParentID: 147}]);
});

it(`Should not clear selection from keyboard shift-state on non-primary click`, () => {
const selectionChangeSpy = spyOn<any>(grid.onRangeSelection, 'emit').and.callThrough();
let cell = grid.getCellByColumn(1, 'ParentID');
UIInteractions.simulateClickAndSelectCellEvent(cell);
fix.detectChanges();
HelperUtils.verifyCellSelected(cell);
HelperUtils.verifySelectedRange(grid, 1, 1, 1, 1);

UIInteractions.triggerKeyDownEvtUponElem('arrowdown', cell.nativeElement, true, false, true);

fix.detectChanges();

expect(selectionChangeSpy).toHaveBeenCalledTimes(1);
HelperUtils.verifyCellsRegionSelected(grid, 1, 2, 1, 1);

cell = grid.getCellByColumn(2, 'ParentID');
UIInteractions.triggerKeyDownEvtUponElem('arrowright', cell.nativeElement, true, false, true);
fix.detectChanges();

expect(selectionChangeSpy).toHaveBeenCalledTimes(2);
HelperUtils.verifyCellsRegionSelected(grid, 1, 2, 1, 2);

UIInteractions.simulateNonPrimaryClick(cell);
fix.detectChanges();

expect(selectionChangeSpy).toHaveBeenCalledTimes(2);
HelperUtils.verifyCellsRegionSelected(grid, 1, 2, 1, 2);
});

it(`Should not clear range when try to navigate out the grid with shift
+ arrrow keys and then click on other cell with pressed Ctrl'`, () => {
pending('# Issue should be fixedy');
Expand Down Expand Up @@ -2427,6 +2452,29 @@ describe('IgxGrid - Multi Cell selection', () => {
expect(grid.getSelectedData()).toEqual(selectedData);
});

it('CRUD: Non-primary click with a cell in edit mode', () => {
grid.getColumnByName('Name').editable = true;
fix.detectChanges();

const cell = grid.getCellByColumn(0, 'Name');
UIInteractions.simulateClickAndSelectCellEvent(cell);
fix.detectChanges();

cell.setEditMode(true);
cell.editValue = 'No name';
fix.detectChanges();

const target = grid.getCellByColumn(0, 'Age');
UIInteractions.simulateNonPrimaryClick(target);
fix.detectChanges();

expect(cell.editMode).toEqual(false);
expect(cell.value).toMatch('No name');
expect(target.focused).toEqual(true);
expect(target.selected).toEqual(false);
expect(cell.selected).toEqual(true);
});

it('Search: selection range should be preserved when perform search', () => {
const range = { rowStart: 2, rowEnd: 4, columnStart: 'ID', columnEnd: 'HireDate' };
grid.selectRange(range);
Expand Down
Loading

0 comments on commit 54fcb72

Please sign in to comment.