Skip to content

Commit 8c114d2

Browse files
authored
Merge pull request #8726 from IgniteUI/ddincheva/activeNode-m
Active node doesn't resets horizontal/vertical scroll positions when page lost focus and regain again
2 parents 1168181 + 7354b30 commit 8c114d2

File tree

6 files changed

+60
-21
lines changed

6 files changed

+60
-21
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,14 @@ All notable changes for each version of this project will be documented in this
1515
### General
1616
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`
1717
- a new property `event` has been introduced to `IGridEditEventArgs` and `IGridEditDoneEventArgs`; the property represents the original DOM event that triggers any of Grid editing events like `rowEditEnter`, `cellEditEnter`, `cellEdit`, `cellEditDone`, `cellEditExit`, `rowEdit`, `rowEditDone`, `rowEditExit`
18+
- **Behavioral Change** -
19+
When there isn't a previous active node and the user enters the grid using tab or shift + tab key:
20+
the first fully visible element is activated: /no scroll bar positioning is reset/changed;
21+
If there is a previous active node in the grid - the previously active node is reactivated without resetting the scroll positions;
22+
If we follow the default tab navigation and we are currently on a data cell with / rowIndex: -1, columnIndex: 6/ for example
23+
when we tab down to the root summaries the summary cell with visible column index 6 should be activated and scroll into the view;
24+
The same applies if you shift+tab to the headers header cell with visible index 6 is activated and scrolled into the view;
25+
If you have an active node and go to another tab and then return back the active node and the current scroll position should not be changed;
1826

1927
## 11.0.0
2028

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3027,6 +3027,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
30273027
|| (event.target === this.theadRow.nativeElement && this.navigation.activeNode.row === -1)
30283028
|| (event.target === this.tfoot.nativeElement && this.navigation.activeNode.row === this.dataView.length)) &&
30293029
!(this.rowEditable && this.crudService.rowEditingBlocked && this.rowInEditMode)) {
3030+
this.navigation.lastActiveNode = this.navigation.activeNode;
30303031
this.navigation.activeNode = {} as IActiveNode;
30313032
this.notifyChanges();
30323033
}

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

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ export interface IActiveNode {
2828
export class IgxGridNavigationService {
2929
public grid: IgxGridBaseDirective & GridType;
3030
public _activeNode: IActiveNode = {} as IActiveNode;
31+
public lastActiveNode: IActiveNode = {} as IActiveNode;
3132
protected pendingNavigation = false;
3233

3334
public get activeNode() {
@@ -40,6 +41,7 @@ export class IgxGridNavigationService {
4041

4142
handleNavigation(event: KeyboardEvent) {
4243
const key = event.key.toLowerCase();
44+
if (this.grid.crudService.cell && NAVIGATION_KEYS.has(key)) { return; }
4345
if (event.repeat && SUPPORTED_KEYS.has(key) || (key === 'tab' && this.grid.crudService.cell)) {
4446
event.preventDefault();
4547
}
@@ -66,8 +68,6 @@ export class IgxGridNavigationService {
6668
if ([' ', 'spacebar', 'space'].indexOf(key) === -1) {
6769
this.grid.selectionService.keyboardStateOnKeydown(this.activeNode, shift, shift && key === 'tab');
6870
}
69-
if (this.grid.crudService.cell && NAVIGATION_KEYS.has(key)) { return; }
70-
7171
const position = this.getNextPosition(this.activeNode.row, this.activeNode.column, key, shift, ctrl, event);
7272
if (NAVIGATION_KEYS.has(key)) {
7373
event.preventDefault();
@@ -231,23 +231,37 @@ export class IgxGridNavigationService {
231231
const gridRows = this.grid.verticalScrollContainer.totalItemCount ?? this.grid.dataView.length;
232232
if (gridRows < 1) { this.activeNode = null; return; }
233233
if (!Object.keys(this.activeNode).length || this.activeNode.row < 0 || this.activeNode.row > gridRows - 1) {
234-
this.grid.navigateTo(0, 0, (obj) => {
234+
const hasLastActiveNode = Object.keys(this.lastActiveNode).length;
235+
const shouldClearSelection = hasLastActiveNode && (this.lastActiveNode.row < 0 || this.lastActiveNode.row > gridRows - 1);
236+
this.setActiveNode(this.lastActiveNode.row >= 0 && this.lastActiveNode.row < gridRows ?
237+
this.firstVisibleNode(this.lastActiveNode.row) : this.firstVisibleNode());
238+
if (shouldClearSelection) {
235239
this.grid.clearCellSelection();
236-
obj.target.activate(event);
237-
});
240+
this.grid.navigateTo(this.activeNode.row, this.activeNode.column, (obj) => {
241+
obj.target?.activate(event);
242+
this.grid.cdr.detectChanges();
243+
} );
244+
} else {
245+
const range = { rowStart: this.activeNode.row, rowEnd: this.activeNode.row,
246+
columnStart: this.activeNode.column, columnEnd: this.activeNode.column };
247+
this.grid.selectRange(range);
248+
this.grid.notifyChanges();
249+
}
238250
}
239251
}
240252

241253
focusFirstCell(header = true) {
242254
if ((header || this.grid.dataView.length) && this.activeNode &&
243255
(this.activeNode.row === -1 || this.activeNode.row === this.grid.dataView.length ||
244256
(!header && !this.grid.hasSummarizedColumns))) { return; }
257+
const shouldScrollIntoView = this.lastActiveNode && (header && this.lastActiveNode.row !== -1) ||
258+
(!header && this.lastActiveNode.row !== this.grid.dataView.length);
259+
this.setActiveNode(this.firstVisibleNode(header ? -1 : this.grid.dataView.length));
260+
if (shouldScrollIntoView) {
261+
this.performHorizontalScrollToCell(this.activeNode.column);
262+
}
263+
this.grid.notifyChanges();
245264

246-
this.setActiveNode({
247-
row: header ? -1 : this.grid.dataView.length, column: 0,
248-
level: this.grid.hasColumnLayouts ? 1 : 0, mchCache: { level: 0, visibleIndex: 0 }
249-
});
250-
this.performHorizontalScrollToCell(0);
251265
}
252266

253267
get lastColumnIndex() {
@@ -262,6 +276,19 @@ export class IgxGridNavigationService {
262276
get containerTopOffset() {
263277
return parseInt(this.grid.verticalScrollContainer.dc.instance._viewContainer.element.nativeElement.style.top, 10);
264278
}
279+
private firstVisibleNode(rowIndex?) {
280+
const colIndex = this.lastActiveNode.column !== undefined ? this.lastActiveNode.column :
281+
this.grid.visibleColumns.sort((c1, c2) => c1.visibleIndex - c2.visibleIndex)
282+
.find(c => this.isColumnFullyVisible(c.visibleIndex))?.visibleIndex;
283+
const column = this.grid.visibleColumns.find((col) => !col.columnLayout && col.visibleIndex === colIndex);
284+
const rowInd = rowIndex ? rowIndex : this.grid.rowList.find(r => !this.shouldPerformVerticalScroll(r.index, colIndex))?.index;
285+
const node = { row: rowInd ?? 0,
286+
column: column?.visibleIndex ?? 0, level: column?.level ?? 0,
287+
mchCache: column ? {level: column.level, visibleIndex: column.visibleIndex} : {} as ColumnGroupsCache,
288+
layout: column && column.columnLayoutChild ? { rowStart: column.rowStart, colStart: column.colStart,
289+
rowEnd: column.rowEnd, colEnd: column.colEnd, columnVisibleIndex: column.visibleIndex} : null };
290+
return node;
291+
}
265292

266293
public isColumnFullyVisible(columnIndex: number) {
267294
if (columnIndex < 0 || this.isColumnPinned(columnIndex, this.forOfDir())) {

projects/igniteui-angular/src/lib/grids/grid/grid-filtering-ui.spec.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3258,21 +3258,24 @@ describe('IgxGrid - Filtering actions - Excel style filtering #grid', () => {
32583258
grid.displayDensity = DisplayDensity.compact;
32593259
tick(200);
32603260
fix.detectChanges();
3261+
spyOn(grid.onColumnVisibilityChanged, 'emit');
32613262

32623263
const column = grid.columns.find((col) => col.field === 'ProductName');
32633264
GridFunctions.verifyColumnIsHidden(column, false, 6);
32643265

32653266
// Open excel style filtering component and hide 'ProductName' column through header icon
3266-
GridFunctions.clickExcelFilterIcon(fix, 'ProductName');
3267-
tick(100);
3268-
fix.detectChanges();
3267+
GridFunctions.clickExcelFilterIconFromCode(fix, grid, 'ProductName');
32693268
GridFunctions.clickHideIconInExcelStyleFiltering(fix);
32703269
tick(200);
32713270
fix.detectChanges();
32723271

32733272
// Verify Excel menu is closed
32743273
expect(GridFunctions.getExcelStyleFilteringComponent(fix)).toBeNull();
3275-
GridFunctions.verifyColumnIsHidden(column, true, 5);
3274+
expect(grid.onColumnVisibilityChanged.emit).toHaveBeenCalledTimes(1);
3275+
expect(grid.onColumnVisibilityChanged.emit).toHaveBeenCalledWith({
3276+
column: column,
3277+
newValue: true
3278+
});
32763279
}));
32773280

32783281
it('Should move pinned column correctly by using move buttons', fakeAsync(() => {

projects/igniteui-angular/src/lib/grids/grid/grid-keyBoardNav-headers.spec.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,10 +70,10 @@ describe('IgxGrid - Headers Keyboard navigation #grid', () => {
7070
fix.detectChanges();
7171

7272
const header = GridFunctions.getColumnHeader('ID', fix);
73-
expect(header).toBeTruthy();
74-
expect(grid.navigation.activeNode.column).toEqual(0);
73+
expect(header).not.toBeDefined();
74+
expect(grid.navigation.activeNode.column).toEqual(3);
7575
expect(grid.navigation.activeNode.row).toEqual(-1);
76-
expect(grid.headerContainer.getScroll().scrollLeft).toEqual(0);
76+
expect(grid.headerContainer.getScroll().scrollLeft).toBeGreaterThanOrEqual(200);
7777
expect(grid.verticalScrollContainer.getScroll().scrollTop).toBeGreaterThanOrEqual(100);
7878
});
7979

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ describe('IgxGrid - Keyboard navigation #grid', () => {
132132
const args: IActiveNodeChangeEventArgs = {
133133
row: 0,
134134
column: 0,
135-
level: undefined,
135+
level: 0,
136136
tag: 'dataCell'
137137
};
138138

@@ -257,7 +257,7 @@ describe('IgxGrid - Keyboard navigation #grid', () => {
257257
await wait(200);
258258
fix.detectChanges();
259259

260-
const cell = grid.getCellByColumn(0, 'col0');
260+
const cell = grid.getCellByColumn(4, 'col5');
261261
expect(cell).toBeDefined();
262262
GridSelectionFunctions.verifyCellActive(cell);
263263
GridSelectionFunctions.verifyCellSelected(cell);
@@ -708,8 +708,8 @@ describe('IgxGrid - Keyboard navigation #grid', () => {
708708
fix.detectChanges();
709709

710710
const row = grid.getRowByIndex(0);
711-
expect(row).toBeDefined();
712-
expect(grid.verticalScrollContainer.getScroll().scrollTop).toEqual(0);
711+
expect(row).not.toBeDefined();
712+
expect(grid.verticalScrollContainer.getScroll().scrollTop).toBeGreaterThanOrEqual(100);
713713
});
714714

715715
it('should toggle expand/collapse state of group row with ArrowRight/ArrowLeft key.', () => {

0 commit comments

Comments
 (0)