Skip to content

Commit 8574be5

Browse files
authored
Merge pull request #8725 from IgniteUI/ddincheva/activeNode-10.2.x
Active node doesn't resets horizontal/vertical scroll positions when page lost focus and regain again - 10.2.x
2 parents 3c7c6dd + 160c438 commit 8574be5

File tree

6 files changed

+65
-22
lines changed

6 files changed

+65
-22
lines changed

CHANGELOG.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,18 @@
11
# Ignite UI for Angular Change Log
22

33
All notable changes for each version of this project will be documented in this file.
4+
5+
## 10.2.9
6+
### General
7+
- `IgxGrid`, `IgxTreeGrid`, `IgxHierarchicalGrid`
8+
- **Behavioral Change** -
9+
When there isn't a previous active node and the user enters the grid using tab or shift + tab key:
10+
the first fully visible element is activated: /no scroll bar positioning is reset/changed;
11+
If there is a previous active node in the grid - the previously active node is reactivated without resetting the scroll positions;
12+
If we follow the default tab navigation and we are currently on a data cell with / rowIndex: -1, columnIndex: 6/ for example
13+
when we tab down to the root summaries the summary cell with visible column index 6 should be activated and scroll into the view;
14+
The same applies if you shift+tab to the headers header cell with visible index 6 is activated and scrolled into the view;
15+
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;
416
## 10.2.0
517

618
### General
@@ -78,7 +90,7 @@ All notable changes for each version of this project will be documented in this
7890
return result;
7991
}
8092
}
81-
```
93+
```
8294
- A new `pipeArgs` input property is exposed by the `IgxColumnComponent`, which is used to pass arguments to the Angular `DatePipe` and `DecimalPipe`, to format the display for date and numeric columns.
8395
```typescript
8496
- ` IGX_INPUT_GROUP_TYPE` injection token

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2994,6 +2994,7 @@ export abstract class IgxGridBaseDirective extends DisplayDensityBase implements
29942994
|| (event.target === this.theadRow.nativeElement && this.navigation.activeNode.row === -1)
29952995
|| (event.target === this.tfoot.nativeElement && this.navigation.activeNode.row === this.dataView.length)) &&
29962996
!(this.rowEditable && this.crudService.rowEditingBlocked && this.rowInEditMode)) {
2997+
this.navigation.lastActiveNode = this.navigation.activeNode;
29972998
this.navigation.activeNode = {} as IActiveNode;
29982999
this.notifyChanges();
29993000
}

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

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

3233
public get activeNode() {
@@ -39,6 +40,7 @@ export class IgxGridNavigationService {
3940

4041
handleNavigation(event: KeyboardEvent) {
4142
const key = event.key.toLowerCase();
43+
if (this.grid.crudService.cell && NAVIGATION_KEYS.has(key)) { return; }
4244
if (event.repeat && SUPPORTED_KEYS.has(key) || (key === 'tab' && this.grid.crudService.cell)) {
4345
event.preventDefault();
4446
}
@@ -65,8 +67,6 @@ export class IgxGridNavigationService {
6567
if ([' ', 'spacebar', 'space'].indexOf(key) === -1) {
6668
this.grid.selectionService.keyboardStateOnKeydown(this.activeNode, shift, shift && key === 'tab');
6769
}
68-
if (this.grid.crudService.cell && NAVIGATION_KEYS.has(key)) { return; }
69-
7070
const position = this.getNextPosition(this.activeNode.row, this.activeNode.column, key, shift, ctrl, event);
7171
if (NAVIGATION_KEYS.has(key)) {
7272
event.preventDefault();
@@ -222,23 +222,37 @@ export class IgxGridNavigationService {
222222
const gridRows = this.grid.verticalScrollContainer.totalItemCount ?? this.grid.dataView.length;
223223
if (gridRows < 1) { this.activeNode = null; return; }
224224
if (!Object.keys(this.activeNode).length || this.activeNode.row < 0 || this.activeNode.row > gridRows - 1) {
225-
this.grid.navigateTo(0, 0, (obj) => {
225+
const hasLastActiveNode = Object.keys(this.lastActiveNode).length;
226+
const shouldClearSelection = hasLastActiveNode && (this.lastActiveNode.row < 0 || this.lastActiveNode.row > gridRows - 1);
227+
this.setActiveNode(this.lastActiveNode.row >= 0 && this.lastActiveNode.row < gridRows ?
228+
this.firstVisibleNode(this.lastActiveNode.row) : this.firstVisibleNode());
229+
if (shouldClearSelection) {
226230
this.grid.clearCellSelection();
227-
obj.target.activate(event);
228-
});
231+
this.grid.navigateTo(this.activeNode.row, this.activeNode.column, (obj) => {
232+
obj.target?.activate(event);
233+
this.grid.cdr.detectChanges();
234+
} );
235+
} else {
236+
const range = { rowStart: this.activeNode.row, rowEnd: this.activeNode.row,
237+
columnStart: this.activeNode.column, columnEnd: this.activeNode.column };
238+
this.grid.selectRange(range);
239+
this.grid.notifyChanges();
240+
}
229241
}
230242
}
231243

232244
focusFirstCell(header = true) {
233245
if ((header || this.grid.dataView.length) && this.activeNode &&
234246
(this.activeNode.row === -1 || this.activeNode.row === this.grid.dataView.length ||
235247
(!header && !this.grid.hasSummarizedColumns))) { return; }
248+
const shouldScrollIntoView = this.lastActiveNode && (header && this.lastActiveNode.row !== -1) ||
249+
(!header && this.lastActiveNode.row !== this.grid.dataView.length);
250+
this.setActiveNode(this.firstVisibleNode(header ? -1 : this.grid.dataView.length));
251+
if (shouldScrollIntoView) {
252+
this.performHorizontalScrollToCell(this.activeNode.column);
253+
}
254+
this.grid.notifyChanges();
236255

237-
this.setActiveNode({
238-
row: header ? -1 : this.grid.dataView.length, column: 0,
239-
level: this.grid.hasColumnLayouts ? 1 : 0, mchCache: { level: 0, visibleIndex: 0 }
240-
});
241-
this.performHorizontalScrollToCell(0);
242256
}
243257

244258
get lastColumnIndex() {
@@ -253,6 +267,19 @@ export class IgxGridNavigationService {
253267
get containerTopOffset() {
254268
return parseInt(this.grid.verticalScrollContainer.dc.instance._viewContainer.element.nativeElement.style.top, 10);
255269
}
270+
private firstVisibleNode(rowIndex?) {
271+
const colIndex = this.lastActiveNode.column !== undefined ? this.lastActiveNode.column :
272+
this.grid.visibleColumns.sort((c1, c2) => c1.visibleIndex - c2.visibleIndex)
273+
.find(c => this.isColumnFullyVisible(c.visibleIndex))?.visibleIndex;
274+
const column = this.grid.visibleColumns.find((col) => !col.columnLayout && col.visibleIndex === colIndex);
275+
const rowInd = rowIndex ? rowIndex : this.grid.rowList.find(r => !this.shouldPerformVerticalScroll(r.index, colIndex))?.index;
276+
const node = { row: rowInd ?? 0,
277+
column: column?.visibleIndex ?? 0, level: column?.level ?? 0,
278+
mchCache: column ? {level: column.level, visibleIndex: column.visibleIndex} : {} as ColumnGroupsCache,
279+
layout: column && column.columnLayoutChild ? { rowStart: column.rowStart, colStart: column.colStart,
280+
rowEnd: column.rowEnd, colEnd: column.colEnd, columnVisibleIndex: column.visibleIndex} : null };
281+
return node;
282+
}
256283

257284
public isColumnFullyVisible(columnIndex: number) {
258285
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)