Skip to content

Commit 50af64b

Browse files
DataGrid - TextArea editor should have the aria-invalid attribute when invalid (T1296376) (#32875)
1 parent 4adcbb9 commit 50af64b

5 files changed

Lines changed: 74 additions & 11 deletions

File tree

packages/devextreme/js/__internal/grids/grid_core/__tests__/__mock__/model/cell/data_cell.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
import { TextBoxModel } from '@ts/ui/__tests__/__mock__/model/textbox';
2-
31
const SELECTORS = {
42
editCell: 'dx-editor-cell',
53
invalidCell: 'invalid',
6-
textBox: 'dx-textbox',
4+
widget: 'dx-widget',
75
};
86

97
export class DataCellModel {
@@ -31,8 +29,8 @@ export class DataCellModel {
3129
return this.root?.innerHTML ?? '';
3230
}
3331

34-
public getEditor(): TextBoxModel {
35-
const editorElement = this.root?.querySelector(`.${SELECTORS.textBox}`) as HTMLElement;
36-
return new TextBoxModel(editorElement);
32+
public getEditor<T>(EditorModel: new (element: HTMLElement) => T): T {
33+
const editorElement = this.root?.querySelector(`.${SELECTORS.widget}`) as HTMLElement;
34+
return new EditorModel(editorElement);
3735
}
3836
}

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,9 @@ export const EDITING_EDITCOLUMNNAME_OPTION_NAME = 'editing.editColumnName';
1414

1515
export const TARGET_COMPONENT_NAME = 'targetComponent';
1616

17+
export const EDITORS_TEXTAREA_SELECTOR = 'textarea:not([hidden])';
1718
export const EDITORS_INPUT_SELECTOR = 'input:not([type=\'hidden\'])';
18-
export const FOCUSABLE_ELEMENT_SELECTOR = `[tabindex]:not([disabled]), ${EDITORS_INPUT_SELECTOR}:not([disabled])`;
19+
export const FOCUSABLE_ELEMENT_SELECTOR = `[tabindex]:not([disabled]), ${EDITORS_INPUT_SELECTOR}:not([disabled]), ${EDITORS_TEXTAREA_SELECTOR}:not([disabled])`;
1920

2021
export const EDIT_MODE_BATCH = 'batch';
2122
export const EDIT_MODE_ROW = 'row';

packages/devextreme/js/__internal/grids/grid_core/validating/__tests__/validating.integration.test.ts

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ import {
66
beforeTest,
77
createDataGrid,
88
} from '@ts/grids/grid_core/__tests__/__mock__/helpers/utils';
9+
import { TextAreaModel } from '@ts/ui/__tests__/__mock__/model/text_area';
10+
import { TextBoxModel } from '@ts/ui/__tests__/__mock__/model/textbox';
911

1012
describe('DataGrid Cell Editing', () => {
1113
beforeEach(beforeTest);
@@ -42,7 +44,7 @@ describe('DataGrid Cell Editing', () => {
4244
});
4345

4446
const firstCell = component.getDataCell(0, 0);
45-
const firstEditor = firstCell.getEditor();
47+
const firstEditor = firstCell.getEditor(TextBoxModel);
4648

4749
firstEditor.setValue('');
4850
jest.runAllTimers();
@@ -56,7 +58,7 @@ describe('DataGrid Cell Editing', () => {
5658
expect(component.getDataCell(0, 0).isValidCell).toBe(true);
5759

5860
const secondCell = component.getDataCell(1, 0);
59-
const secondEditor = secondCell.getEditor();
61+
const secondEditor = secondCell.getEditor(TextBoxModel);
6062

6163
secondEditor.setValue('');
6264
jest.runAllTimers();
@@ -70,4 +72,40 @@ describe('DataGrid Cell Editing', () => {
7072
expect(component.getDataCell(1, 0).isValidCell).toBe(true);
7173
});
7274
});
75+
76+
// T1296376
77+
describe('when a TextArea editor is invalid', () => {
78+
it('should have the aria-invalid attribute set to true', async () => {
79+
const { component, instance } = await createDataGrid({
80+
dataSource: [
81+
{ id: 1, text: 'value' },
82+
],
83+
keyExpr: 'id',
84+
columns: [{
85+
dataField: 'text',
86+
validationRules: [{ type: 'required' }],
87+
}],
88+
editing: {
89+
mode: 'cell',
90+
allowUpdating: true,
91+
},
92+
onEditorPreparing(e) {
93+
e.editorName = 'dxTextArea';
94+
},
95+
});
96+
97+
instance.editCell(0, 0);
98+
jest.runAllTimers();
99+
const textCell = component.getDataCell(0, 0);
100+
101+
expect(textCell.isEditCell).toBe(true);
102+
103+
const editor = textCell.getEditor(TextAreaModel);
104+
editor.setValue('');
105+
jest.runAllTimers();
106+
107+
expect(component.getDataCell(0, 0).isValidCell).toBe(false);
108+
expect(editor.getInputElement().getAttribute('aria-invalid')).toBe('true');
109+
});
110+
});
73111
});

packages/devextreme/js/__internal/grids/grid_core/validating/m_validating.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import type { DataController } from '@ts/grids/grid_core/data_controller/m_data_
3131
import type { EditorFactory } from '@ts/grids/grid_core/editor_factory/m_editor_factory';
3232
import type { RowsView } from '@ts/grids/grid_core/views/m_rows_view';
3333

34-
import { EDITORS_INPUT_SELECTOR } from '../editing/const';
34+
import { EDITORS_INPUT_SELECTOR, EDITORS_TEXTAREA_SELECTOR } from '../editing/const';
3535
import type { EditingController } from '../editing/m_editing';
3636
import type { NormalizedEditCellOptions } from '../editing/types';
3737
import modules from '../m_modules';
@@ -1442,7 +1442,8 @@ export const validatingEditorFactoryExtender = (Base: ModuleType<EditorFactory>)
14421442

14431443
private _getCurrentFocusElement($focus) {
14441444
if (this._editingController.isEditing()) {
1445-
return $focus.find(EDITORS_INPUT_SELECTOR).first();
1445+
const selector = [EDITORS_INPUT_SELECTOR, EDITORS_TEXTAREA_SELECTOR].join(', ');
1446+
return $focus.find(selector).first();
14461447
}
14471448
return $focus;
14481449
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import TextArea from '@ts/ui/m_text_area';
2+
3+
const CLASSES = {
4+
textArea: 'dx-texteditor-input',
5+
};
6+
7+
export class TextAreaModel {
8+
constructor(protected readonly root: HTMLElement) {}
9+
10+
public getElement(): HTMLElement {
11+
return this.root;
12+
}
13+
14+
public getInputElement(): HTMLTextAreaElement {
15+
return this.root.querySelector(`.${CLASSES.textArea}`) as HTMLTextAreaElement;
16+
}
17+
18+
public setValue(value: string): void {
19+
this.getInstance()?.option('value', value);
20+
}
21+
22+
public getInstance(): TextArea {
23+
return TextArea.getInstance(this.root);
24+
}
25+
}

0 commit comments

Comments
 (0)