Skip to content

Commit

Permalink
DataGrid: Fix focus looping in certain cases if the first column has …
Browse files Browse the repository at this point in the history
…a DropDownButton (T1185341) (#25497)

Co-authored-by: Alyar <>
  • Loading branch information
Alyar666 authored Sep 4, 2023
1 parent a54cedc commit 81ea35e
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -884,17 +884,17 @@ export class KeyboardNavigationController extends modules.ViewController {
_targetCellTabHandler(eventArgs, direction) {
const $event = eventArgs.originalEvent;
let eventTarget = $event.target;
let elementType = this._getElementType(eventTarget);
let $cell = this._getCellElementFromTarget(eventTarget);
const $lastInteractiveElement = this._getInteractiveElement(
const $lastInteractiveElement = elementType === 'cell' && this._getInteractiveElement(
$cell,
!eventArgs.shift,
);
let isOriginalHandlerRequired = false;
let elementType;

if (
!isEditorCell(this, $cell)
&& $lastInteractiveElement.length
&& $lastInteractiveElement?.length
&& eventTarget !== $lastInteractiveElement.get(0)
) {
isOriginalHandlerRequired = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { Selector } from 'testcafe';
import FocusableElement from '../../internal/focusable';
import Widget from '../../internal/widget';
import { CellEditor } from './cellEditor';
import DropDownButton from '../../dropDownButton';

const CLASS = {
hiddenColumn: 'hidden-column',
editCell: 'dx-editor-cell',
focused: 'dx-focused',
dropDownButton: 'dx-dropdownbutton',
editorInput: 'dx-texteditor-input',
invalidCell: 'dx-datagrid-invalid',
invalidOverlayMessage: 'dx-invalid-message',
Expand Down Expand Up @@ -57,6 +59,10 @@ export default class DataCell extends FocusableElement {
return this.element.find(`.${CLASS.checkbox}`);
}

getDropDownButton(): DropDownButton {
return new DropDownButton(this.element.find(`.${CLASS.dropDownButton}`));
}

getLinkEdit(): Selector {
return this.element.find(`.${CLASS.linkEdit}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ const CLASS = {
export default abstract class DropDownList extends TextBox {
dropDownButton: Selector;

constructor(id: string) {
constructor(id: string | Selector) {
super(id);
this.dropDownButton = this.element.find(`.${CLASS.dropDownButton}`);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4272,3 +4272,105 @@ test('Focus position should be correct when open second adaptive row', async (t)
width: 600,
columnWidth: 200,
}));

// T1185341
test('Focus first cell with dropDownButton (via tab key) -> open dropDownButton list (via up key)-> close dropDownButton list (via esc key) -> navigation to the right when focusedRowEnabled is true', async (t) => {
const dataGrid = new DataGrid('#container');
const headers = dataGrid.getHeaders();
const headerRow = headers.getHeaderRow(0);

await t
.expect(dataGrid.isReady())
.ok();

const dropDownButton = dataGrid.getDataCell(0, 0).getDropDownButton();

await t
.pressKey('tab')
.expect(headerRow.getHeaderCell(0).element.focused)
.ok('First header is focused')

.pressKey('ctrl+down')
.expect(dataGrid.getDataRow(0).isFocusedRow)
.ok('First row is focused')
.expect(dataGrid.getDataCell(0, 0).isFocused)
.ok('First cell is focused')

.pressKey('up');

let isDropDownButtonOpened = await dropDownButton.isOpened();

await t
.expect(isDropDownButtonOpened)
.ok('dropDownButton is opened');

await t.pressKey('esc');

isDropDownButtonOpened = await dropDownButton.isOpened();

await t
.expect(isDropDownButtonOpened)
.notOk('dropDownButton is closed')

.pressKey('right')
.expect(dataGrid.getDataCell(0, 1).isFocused)
.ok('Second cell is focused');
}).before(async () => createWidget('dxDataGrid', {
dataSource: [
{
id: 0, field1: 'test1', field2: 'test2', field3: 'test3',
},
{
id: 0, field1: 'test4', field2: 'test5', field3: 'test6',
},
],
keyExpr: 'id',
focusedRowEnabled: true,
columns: [{
dataField: 'field1',
cellTemplate() {
return ($('<div />') as any).dxDropDownButton({
text: 'Action',
});
},
}, 'field2', 'field3'],
}, undefined, { disableFxAnimation: true }));

// T1185341
test('Focus second cell (via click) -> tab navigation when focusedRowEnabled is true', async (t) => {
const dataGrid = new DataGrid('#container');

await t
.expect(dataGrid.isReady())
.ok();

await t
.click(dataGrid.getDataCell(0, 1).element)

.expect(dataGrid.getDataRow(0).isFocusedRow)
.ok('First row is focused')

.pressKey('tab')

.expect(dataGrid.getDataCell(0, 2).isFocused)
.ok('Second cell is focused');
}).before(async () => createWidget('dxDataGrid', {
dataSource: [
{
id: 0, field1: 'test1', field2: 'test2', field3: 'test3',
},
{
id: 0, field1: 'test4', field2: 'test5', field3: 'test6',
},
],
keyExpr: 'id',
focusedRowEnabled: true,
columns: [{
dataField: 'field1',
cellTemplate() {
return ($('<div />') as any).dxDropDownButton({
text: 'Action',
});
},
}, 'field2', 'field3'],
}, undefined, { disableFxAnimation: true }));

0 comments on commit 81ea35e

Please sign in to comment.