Skip to content

Commit 5316974

Browse files
DataGrid - Fix the browser scrolling back to the grid when data is updated (T1310557) (#33168)
1 parent c7a6871 commit 5316974

File tree

3 files changed

+104
-11
lines changed

3 files changed

+104
-11
lines changed

packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/m_keyboard_navigation.ts

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1743,7 +1743,7 @@ export class KeyboardNavigationController extends KeyboardNavigationControllerCo
17431743
gridCoreUtils.focusAndSelectElement(this, $focusedElement);
17441744
}
17451745

1746-
public _focus($cell, disableFocus?, skipFocusEvent?) {
1746+
public _focus($cell: dxElementWrapper, disableFocus?: boolean, skipFocusEvent?: boolean, preventScroll?: boolean) {
17471747
const $row = $cell && !$cell.hasClass(ROW_CLASS)
17481748
? $cell.closest(`.${ROW_CLASS}`)
17491749
: $cell;
@@ -1795,8 +1795,12 @@ export class KeyboardNavigationController extends KeyboardNavigationControllerCo
17951795
});
17961796
if (!skipFocusEvent) {
17971797
this._applyTabIndexToElement($focusElement);
1798-
// @ts-expect-error
1799-
eventsEngine.trigger($focusElement, 'focus');
1798+
if (preventScroll) {
1799+
$focusElement.get(0)?.focus({ preventScroll });
1800+
} else {
1801+
// @ts-expect-error
1802+
eventsEngine.trigger($focusElement, 'focus');
1803+
}
18001804
}
18011805
if (disableFocus) {
18021806
$focusElement.addClass(CELL_FOCUS_DISABLED_CLASS);
@@ -1809,7 +1813,7 @@ export class KeyboardNavigationController extends KeyboardNavigationControllerCo
18091813
}
18101814
}
18111815

1812-
public _updateFocus(isRenderView?, skipFocusEvent = false) {
1816+
public _updateFocus(isRenderView: boolean, skipFocusEvent = false) {
18131817
this._updateFocusTimeout = setTimeout(() => {
18141818
if (this._needFocusEditingCell()) {
18151819
this._editingController._focusEditingCell();
@@ -1848,12 +1852,12 @@ export class KeyboardNavigationController extends KeyboardNavigationControllerCo
18481852
);
18491853
return;
18501854
}
1851-
!isFocusedElementDefined && this._focus($cell, false, skipFocusEvent);
1855+
!isFocusedElementDefined && this._focus($cell, false, skipFocusEvent, isRenderView);
18521856
} else if (
18531857
!isFocusedElementDefined
18541858
&& (this._isNeedFocus || this._isHiddenFocus)
18551859
) {
1856-
this._focus($cell, this._isHiddenFocus, skipFocusEvent);
1860+
this._focus($cell, this._isHiddenFocus, skipFocusEvent, isRenderView);
18571861
}
18581862
if (isEditing && !column?.showEditorAlways) {
18591863
this._focusInteractiveElement.bind(this)($cell);
@@ -1953,7 +1957,7 @@ export class KeyboardNavigationController extends KeyboardNavigationControllerCo
19531957
that.setFocusedCellPosition(rowIndex, columnIndex);
19541958
}
19551959

1956-
isUpArrow && that._updateFocus();
1960+
isUpArrow && that._updateFocus(false);
19571961
}
19581962

19591963
// #endregion Focusing
@@ -3128,7 +3132,7 @@ const editing = (Base: ModuleType<EditingController>) => class EditingController
31283132

31293133
protected _processCanceledEditingCell() {
31303134
this.closeEditCell().done(() => {
3131-
this._keyboardNavigationController._updateFocus();
3135+
this._keyboardNavigationController._updateFocus(false);
31323136
});
31333137
}
31343138

@@ -3145,7 +3149,7 @@ const editing = (Base: ModuleType<EditingController>) => class EditingController
31453149
const isFilterCell = !!$focusedElement.closest(`.${this.addWidgetPrefix(FILTER_ROW_CLASS)}`).length;
31463150

31473151
if (!isFilterCell) {
3148-
keyboardNavigation._updateFocus();
3152+
keyboardNavigation._updateFocus(false);
31493153
}
31503154

31513155
return result;

packages/devextreme/js/__internal/grids/grid_core/keyboard_navigation/scrollable_a11y.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,13 @@ export const keyboardNavigationScrollableA11yExtender = (Base: ModuleType<Keyboa
6161
super.renderCompleted(e);
6262
}
6363

64-
public _focus($cell: any, disableFocus?: any, skipFocusEvent?: any): void {
65-
super._focus($cell, disableFocus, skipFocusEvent);
64+
public _focus(
65+
$cell: dxElementWrapper,
66+
disableFocus?: boolean,
67+
skipFocusEvent?: boolean,
68+
preventScroll?: boolean,
69+
): void {
70+
super._focus($cell, disableFocus, skipFocusEvent, preventScroll);
6671

6772
this.makeScrollableFocusableIfNeed();
6873
}

packages/devextreme/testing/tests/DevExpress.ui.widgets.dataGrid/focus.integration.tests.js

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4318,6 +4318,90 @@ QUnit.module('View\'s focus', {
43184318
assert.equal(this.dataGrid.option('focusedRowKey'), 2, 'row key is changed');
43194319
assert.ok($(this.dataGrid.getRowElement(1)).hasClass('dx-row-focused'), 'second row is focused');
43204320
});
4321+
4322+
// T1310557
4323+
QUnit.testInActiveWindow('Browser should not scroll back to the grid when a focused cell is updated or rerendered', function(assert) {
4324+
// arrange
4325+
const dataGrid = createDataGrid({
4326+
dataSource: {
4327+
store: new ArrayStore({
4328+
key: 'id',
4329+
data: [{ id: 1, name: 'test1' }],
4330+
}),
4331+
pushAggregationTimeout: 0,
4332+
},
4333+
});
4334+
this.clock.tick(10);
4335+
4336+
try {
4337+
$('body').css('height', 2000);
4338+
window.scrollTo(0, 0);
4339+
4340+
const keyboardController = dataGrid.getController('keyboardNavigation');
4341+
const $firstCell = $(dataGrid.getCellElement(0, 0));
4342+
const scrollPosition = 300;
4343+
4344+
// assert
4345+
assert.strictEqual(window.pageYOffset, 0, 'document scroll is at the top');
4346+
4347+
// act
4348+
$firstCell.trigger(CLICK_EVENT);
4349+
this.clock.tick(10);
4350+
4351+
keyboardController.keyDownHandler({
4352+
key: 'Tab',
4353+
keyName: 'tab',
4354+
originalEvent: $.Event('keydown', { target: $firstCell.get(0) }),
4355+
});
4356+
this.clock.tick(10);
4357+
4358+
// assert
4359+
assert.ok($(dataGrid.getCellElement(0, 1)).hasClass('dx-focused'), 'second cell is focused');
4360+
4361+
// act
4362+
window.scrollTo(0, scrollPosition);
4363+
4364+
// assert
4365+
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is changed');
4366+
4367+
// act
4368+
dataGrid.getDataSource().store().push([{ type: 'update', key: 1, data: { name: 'updated' } }]);
4369+
this.clock.tick(10);
4370+
4371+
// assert
4372+
assert.strictEqual($(dataGrid.getCellElement(0, 1)).text(), 'updated', 'second cell text is updated');
4373+
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after push update');
4374+
4375+
// act
4376+
dataGrid.refresh();
4377+
this.clock.tick(10);
4378+
4379+
// assert
4380+
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after refresh');
4381+
4382+
// act
4383+
dataGrid.repaint();
4384+
this.clock.tick(10);
4385+
4386+
// assert
4387+
assert.strictEqual(window.pageYOffset, scrollPosition, 'document scroll is preserved after repaint');
4388+
4389+
// act
4390+
keyboardController.keyDownHandler({
4391+
key: 'ArrowLeft',
4392+
keyName: 'leftArrow',
4393+
originalEvent: $.Event('keydown', { target: $(dataGrid.getCellElement(0, 1)).get(0) }),
4394+
});
4395+
this.clock.tick(10);
4396+
4397+
// assert
4398+
assert.ok($(dataGrid.getCellElement(0, 0)).hasClass('dx-focused'), 'first cell is focused');
4399+
assert.strictEqual(window.pageYOffset, 0, 'document scroll is changed after keyboard navigation');
4400+
} finally {
4401+
$('body').css('height', '');
4402+
window.scrollTo(0, 0);
4403+
}
4404+
});
43214405
});
43224406

43234407
QUnit.module('API methods', baseModuleConfig, () => {

0 commit comments

Comments
 (0)