Skip to content

Commit 3a632a8

Browse files
authored
DataGrid - Focus gets removed from rowsview when datagrid repaints on focusChanged event - T1224663 (#28715)
1 parent 5fa1852 commit 3a632a8

File tree

3 files changed

+56
-12
lines changed

3 files changed

+56
-12
lines changed

e2e/testcafe-devextreme/tests/dataGrid/focus/focus.ts

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,3 +241,30 @@ test('DataGrid - FilterRow cell loses focus when focusedRowEnabled is true and e
241241
});
242242
});
243243
});
244+
245+
['onFocusedRowChanged', 'onFocusedRowChanging'].forEach((event) => {
246+
test(`Focus should be preserved on datagrid when rowsview repaints in ${event} event (T1224663)`, async (t) => {
247+
const dataGrid = new DataGrid('#container');
248+
249+
await t
250+
.click(dataGrid.getDataCell(0, 0).element)
251+
.expect(dataGrid.getDataRow(0).isFocusedRow)
252+
.ok();
253+
254+
await t
255+
.pressKey('down')
256+
.expect(dataGrid.getDataRow(1).isFocusedRow)
257+
.ok();
258+
}).before(async () => createWidget('dxDataGrid', {
259+
dataSource: [
260+
{ id: 1, name: 'name 1' },
261+
{ id: 2, name: 'name 2' },
262+
{ id: 3, name: 'name 3' },
263+
],
264+
keyExpr: 'id',
265+
focusedRowEnabled: true,
266+
[event]: (e) => {
267+
e.component.repaint();
268+
},
269+
}));
270+
});

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export const ATTRIBUTES = {
44
};
55

66
export const ROWS_VIEW_CLASS = 'rowsview';
7+
export const TABLE_CLASS = 'table';
78
export const EDIT_FORM_CLASS = 'edit-form';
89
export const GROUP_FOOTER_CLASS = 'group-footer';
910
export const ROW_CLASS = 'dx-row';

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

Lines changed: 28 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { dxElementWrapper } from '@js/core/renderer';
66
import $ from '@js/core/renderer';
77
import browser from '@js/core/utils/browser';
88
import { Deferred, when } from '@js/core/utils/deferred';
9+
import { isElementInDom } from '@js/core/utils/dom';
910
import {
1011
getHeight,
1112
getOuterHeight,
@@ -71,6 +72,7 @@ import {
7172
REVERT_BUTTON_CLASS,
7273
ROWS_VIEW,
7374
ROWS_VIEW_CLASS,
75+
TABLE_CLASS,
7476
WIDGET_CLASS,
7577
} from './const';
7678
import { GridCoreKeyboardNavigationDom } from './dom';
@@ -307,18 +309,32 @@ export class KeyboardNavigationController extends modules.ViewController {
307309

308310
this._documentClickHandler = this._documentClickHandler || this.createAction((e) => {
309311
const $target = $(e.event.target);
310-
const isCurrentRowsViewClick = this._isEventInCurrentGrid(e.event)
311-
&& $target.closest(`.${this.addWidgetPrefix(ROWS_VIEW_CLASS)}`).length;
312-
const isEditorOverlay = $target.closest(
313-
`.${DROPDOWN_EDITOR_OVERLAY_CLASS}`,
314-
).length;
315-
const isColumnResizing = !!this._columnResizerController && this._columnResizerController.isResizing();
316-
if (!isCurrentRowsViewClick && !isEditorOverlay && !isColumnResizing) {
317-
const targetInsideFocusedView = this._focusedView
318-
? $target.parents().filter(this._focusedView.element()).length > 0
319-
: false;
320-
321-
!targetInsideFocusedView && this._resetFocusedCell(true);
312+
313+
const tableSelector = `.${this.addWidgetPrefix(TABLE_CLASS)}`;
314+
const rowsViewSelector = `.${this.addWidgetPrefix(ROWS_VIEW_CLASS)}`;
315+
const editorOverlaySelector = `.${DROPDOWN_EDITOR_OVERLAY_CLASS}`;
316+
317+
// if click was on the datagrid table, but the target element is no more presented in the DOM
318+
const needKeepFocus = !!$target.closest(tableSelector).length && !isElementInDom($target);
319+
320+
if (needKeepFocus) {
321+
e.event.preventDefault();
322+
return;
323+
}
324+
325+
const isRowsViewClick = this._isEventInCurrentGrid(e.event) && !!$target.closest(rowsViewSelector).length;
326+
const isEditorOverlayClick = !!$target.closest(editorOverlaySelector).length;
327+
const isColumnResizing = !!this._columnResizerController?.isResizing();
328+
329+
if (!isRowsViewClick && !isEditorOverlayClick && !isColumnResizing) {
330+
const isClickOutsideFocusedView = this._focusedView
331+
? $target.closest(this._focusedView.element()).length === 0
332+
: true;
333+
334+
if (isClickOutsideFocusedView) {
335+
this._resetFocusedCell(true);
336+
}
337+
322338
this._resetFocusedView();
323339
}
324340
});

0 commit comments

Comments
 (0)