Skip to content

Commit cd9a232

Browse files
authored
DataGrid - NVDA reads filter menu items as "Search box 1 of 8" (T1290386) (#29994)
1 parent baf47a9 commit cd9a232

File tree

2 files changed

+53
-14
lines changed
  • e2e/testcafe-devextreme/tests/dataGrid/common/filterRow
  • packages/devextreme/js/__internal/grids/grid_core/filter

2 files changed

+53
-14
lines changed

e2e/testcafe-devextreme/tests/dataGrid/common/filterRow/filterRow.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,3 +193,35 @@ test('Focus overlay should be visible in filter row when focusedRowEnabled is en
193193
}).after(async () => {
194194
await changeTheme('generic.light');
195195
});
196+
197+
test('DataGrid - NVDA reads filter menu items as "Search box 1 of 8" (T1290386)', async (t) => {
198+
const dataGrid = new DataGrid('#container');
199+
const filterEditor = dataGrid.getFilterEditor(0, FilterTextBox);
200+
201+
await dataGrid.isReady();
202+
203+
await t
204+
.expect(filterEditor.menuButton.getAttribute('aria-label'))
205+
.eql('Search box');
206+
207+
await t
208+
.click(filterEditor.menuButton);
209+
210+
const itemCount = await filterEditor.menu.getItemCount();
211+
212+
for (let i = 0; i < itemCount; i += 1) {
213+
const item = filterEditor.menu.getItemByIndex(i);
214+
await t.expect(item.getAttribute('aria-label')).eql(null);
215+
}
216+
217+
await t
218+
.click(filterEditor.menu.getItemByText('Equals'))
219+
.expect(filterEditor.menuButton.getAttribute('aria-label'))
220+
.eql('Equals');
221+
}).before(async () => createWidget('dxDataGrid', {
222+
dataSource: getData(5, 1),
223+
keyExpr: 'field_0',
224+
filterRow: {
225+
visible: true,
226+
},
227+
}));

packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_row.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -589,13 +589,17 @@ const columnHeadersView = (Base: ModuleType<ColumnHeadersView>) => class ColumnH
589589
showFirstSubmenuMode: 'onHover',
590590
hideSubmenuOnMouseLeave: true,
591591
items: [{
592+
name: getColumnSelectedFilterOperation(that, column) || ARIA_SEARCH_BOX,
592593
disabled: !column.filterOperations?.length,
593594
icon: OPERATION_ICONS[getColumnSelectedFilterOperation(that, column) || 'default'],
594595
selectable: false,
595596
items: that._getFilterOperationMenuItems(column),
596597
}],
597-
onItemRendered: ({ itemElement }) => {
598-
this.setAria('label', ARIA_SEARCH_BOX, $(itemElement));
598+
onItemRendered: ({ itemElement, itemData }) => {
599+
if (itemData?.items && itemData?.name) {
600+
const labelText = that._getOperationDescriptionFromDescriptor(itemData.name) || ARIA_SEARCH_BOX;
601+
this.setAria('label', labelText, $(itemElement));
602+
}
599603
},
600604
onItemClick(properties) {
601605
// @ts-expect-error
@@ -688,21 +692,15 @@ const columnHeadersView = (Base: ModuleType<ColumnHeadersView>) => class ColumnH
688692
const that = this;
689693
let result: any = [{}];
690694
const filterRowOptions = that.option('filterRow');
691-
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
692-
const operationDescriptions = filterRowOptions?.operationDescriptions || {};
693695

694696
if (column.filterOperations?.length) {
695697
const availableFilterOperations = column.filterOperations.filter((value) => isDefined(OPERATION_DESCRIPTORS[value]));
696-
result = map(availableFilterOperations, (value) => {
697-
const descriptionName = OPERATION_DESCRIPTORS[value];
698-
699-
return {
700-
name: value,
701-
selected: (getColumnSelectedFilterOperation(that, column) || column.defaultFilterOperation) === value,
702-
text: operationDescriptions[descriptionName],
703-
icon: OPERATION_ICONS[value],
704-
};
705-
});
698+
result = map(availableFilterOperations, (value) => ({
699+
name: value,
700+
selected: (getColumnSelectedFilterOperation(that, column) || column.defaultFilterOperation) === value,
701+
text: that._getOperationDescriptionFromDescriptor(value),
702+
icon: OPERATION_ICONS[value],
703+
}));
706704

707705
result.push({
708706
name: null,
@@ -714,6 +712,15 @@ const columnHeadersView = (Base: ModuleType<ColumnHeadersView>) => class ColumnH
714712
return result;
715713
}
716714

715+
private _getOperationDescriptionFromDescriptor(value) {
716+
const filterRowOptions = this.option('filterRow');
717+
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
718+
const operationDescriptions = filterRowOptions?.operationDescriptions || {};
719+
const descriptionName = OPERATION_DESCRIPTORS[value];
720+
721+
return operationDescriptions[descriptionName];
722+
}
723+
717724
protected _handleDataChanged(e) {
718725
const dataSource = this._dataController?.dataSource?.();
719726
const lastLoadOptions = dataSource?.lastLoadOptions?.();

0 commit comments

Comments
 (0)