Accessibility in Angular Grid component
25 Aug 202524 minutes to read
The Grid component followed the accessibility guidelines and standards, including ADA, Section 508, WCAG 2.2 standards, and WCAG roles that are commonly used to evaluate accessibility.
The accessibility compliance for the Grid component is outlined below.



WAI-ARIA attributes
The Grid component followed the WAI-ARIA patterns to meet the accessibility. The following ARIA attributes are used in the Grid component:
Attributes | Purpose |
---|---|
role=grid |
To represent the element containing the grid component. |
role=row |
To represent the element containing the cells of the row in the grid. |
role=rowgroup |
To represent the group of rows in the grid. |
role=columnheader |
To represent the cell in a row contains header information for a column in the grid. |
role=gridcell |
To represent a cell in the grid component. |
role=button |
To represent the element that acts as a button in the grid. |
role=search |
To represent the element that acts as a search region in the grid. |
role=presentation |
To represent the element to be not available for accessibility concerns. |
role=navigation |
To represent the element containing pager elements to navigate from one page to another. |
aria-colindex |
Defines the column index of the column with respect to the total number of columns within the grid. |
aria-rowindex |
Defines row index of the row with respect to the total number of rows within the grid. |
aria-rowspan |
Defines the number of rows spanned by a cell within the grid. |
aria-colspan |
Defines the number of columns spanned by a cell within the grid. |
aria-rowcount |
Defines the total number of rows in the grid. |
aria-colcount |
Defines the total number of columns in the grid. |
aria-selected |
Indicates the current “selected” state of the rows and cells in the grid. |
aria-expanded |
Indicate if the expand icon in the hierarchy grid or grouped grid or detail grid is expanded or collapsed |
aria-sort |
Indicates whether the data in the grid are sorted in ascending or descending order. |
aria-busy |
Indicates an element is being modified and that assistive technologies may want to wait until the changes are complete before informing the user about the update. |
aria-owns |
Identifies an element in order to define a visual, functional, or contextual relationship between a parent and its child elements. |
aria-hidden |
Hides the element from accessibility concerns. |
aria-labelledby |
Provides an accessible name for the checkbox labels in excel filter, checkbox filter and column chooser dialog. |
aria-describedby |
Provides an description about the features enabled in the header when the grid header cell is focused. |
The Syncfusion Grid component is structured with a two-table architecture for its header and content. To enhance accessibility for screen readers, roles and ARIA attributes are incorporated for both the grid parent and all its child elements. Although this architectural approach may have some limitations with accessibility checker tools. It’s important to note that these limitations do not affect the readability of the grid content over screen readers.
The accessibility checker tools highlights the following known issues:
-
aria-required-children: This warning appears when rendering the grid without any features, as it contains textarea and grid content. Additionally, it appears when enabling features such as the toolbar and grouping.
-
color-contrast: This warning appears when you are enabling the search item in the grid’s toolbar.
-
An explicit ARIA ‘role’ is not valid for
<tr>
element within an ARIA role ‘grid’ per the ARIA in HTML specification. -
An explicit ARIA ‘role’ is not valid for
<th>
element within an ARIA role ‘grid’ per the ARIA in HTML specification. -
An explicit ARIA ‘role’ is not valid for
<td>
element within an ARIA role ‘grid’ per the ARIA in HTML specification. -
The element with role “button” contains descendants with roles “rowgroup” which are ignored by browsers.
-
Content is not within a landmark element.
-
Multiple elements with “search” role do not have unique labels.
-
Text contrast of 4.10 with its background is less than the WCAG AA minimum requirements for text of size 13px and weight of 400.
-
Interactive component with ARIA role ‘grid’ does not have a programmatically associated name.
-
The element with role “rowgroup” is not contained in or owned by an element with one of the following roles: “grid, table, treegrid”.
Keyboard interaction
The Grid component followed the keyboard interaction guideline, making it easy for people who use assistive technologies (AT) and those who completely rely on keyboard navigation. The following keyboard shortcuts are supported by the Grid component.
Pager
Windows | MAC | To do this |
---|---|---|
Tab | Tab | Focus on the next pager item. |
Shift + Tab | Shift + Tab | Focus on the previous pager item. |
Enter / Space | Enter / Space | Select the currently focused page. |
PageUp / Left Arrow | Left Arrow | Navigate to previous page. |
PageDown / Right Arrow | Right Arrow | Navigate to next page. |
Home / Ctrl + Alt + PageUp | Fn + Left Arrow | Navigate to first page. |
End / Ctrl + Alt + PageDown | Fn + Right Arrow | Navigate to last page. |
Focus Elements
Windows | MAC | To do this |
---|---|---|
Home | Fn + Left Arrow | Moves the focus to the first cell of the focused row. |
End | Fn + Right Arrow | Moves the focus to the last cell of the focused row. |
Ctrl + Home | Command + Fn + Left Arrow | Moves the focus to the first Cell of the first row in the grid. |
Ctrl + End | Command + Fn + Right Arrow | Moves the focus to the last Cell of the last row in the grid. |
Up Arrow | Up Arrow | Moves the cell focus upward from the focused cell. |
Down Arrow | Down Arrow | Moves the cell focus downward from the focused cell. |
Right Arrow | Right Arrow | Moves the cell focus right side from the focused cell. |
Left Arrow | Left Arrow | Moves the cell focus left side from the focused cell. |
Alt + J | Alt + J | Moves the focus to the entire grid. |
Alt + W | Alt + W | Move the focus to the grid content element. |
Selection
Windows | MAC | To do this |
---|---|---|
Up Arrow | Up Arrow | Moves up a row/cell selection from the selected row/cell. |
Down Arrow | Down Arrow | Moves down a row/cell selection from the selected row/cell. |
Right Arrow | Right Arrow | Moves to the right cell selection from the selected cell. |
Left Arrow | Left Arrow | Moves to the left cell selection from the selected cell. |
Shift + Up Arrow | Shift + Up Arrow | Extends the row/cell selection upwards from the selected row/cell. |
Shift + Down Arrow | Shift + Down Arrow | Extends the row/cell selection downwards from the selected row/cell. |
Shift + Right Arrow | Shift + Right Arrow | Extends the cell selection to the right side from the selected cell. |
Shift + Left Arrow | Shift + Left Arrow | Extends the cell selection to the left side from the selected cell. |
Enter | Enter | Moves the row/cell selection downward from the selected cell/row. |
Shift + Enter | Shift + Enter | Moves the row/cell selection upward. |
Esc | Esc | Deselects all the selected row/cells. |
Ctrl + A | Ctrl + A | Select all the row/cells in the current page. |
Grouping
Windows | MAC | To do this |
---|---|---|
Ctrl + Up Arrow | Command + Up Arrow | Collapses all visible grouped rows in the grid. |
Ctrl + Down Arrow | Command + Down Arrow | Expands all visible grouped rows in the grid. |
Ctrl + Space | Ctrl + Space | Groups data by the currently focused column header. |
Enter | Enter | Expands or collapses the focused group row, detail row, or child grid. |
Windows | MAC | To do this |
---|---|---|
Ctrl + P | Command + P | Prints the Grid. |
Clipboard
Windows | MAC | To do this |
---|---|---|
Ctrl + C | Command + C | Copies selected rows or cells data into the clipboard. |
Ctrl + Shift + H | Ctrl + Shift + H | Copies selected rows or cells data with header into clipboard |
Editing
Windows | MAC | To do this |
---|---|---|
F2 | F2 | Begins editing the selected row (Normal/Dialog mode) or selected cell (Batch mode). |
Enter | Enter | Saves current form (Normal/Dialog mode) or saves current cell and moves to next row cell (Batch mode). |
Insert | Ctrl + Command + Enter | Creates a new record based on the configured NewRowPosition setting. |
Delete | Delete | Removes the currently selected record from the grid. |
Tab | Tab | Moves to next editable cell (Normal/Dialog mode) or saves current cell and edits next cell (Batch mode). |
Shift + Tab | Shift + Tab | Moves to previous editable cell (Normal/Dialog mode) or saves current cell and edits previous cell (Batch mode). |
Shift + Enter | Shift + Enter | Saves current cell and begins editing the previous row cell (Batch mode). |
Filtering
Windows | MAC | To do this |
---|---|---|
Alt + Down arrow | Alt + Down arrow | Opens the filter menu (Excel, Menu, or CheckBox filter types) when the corresponding header element has focus. |
Column Menu
Windows | MAC | To do this |
---|---|---|
Alt + Down arrow | Alt + Down arrow | Opens the column menu when the corresponding header element has focus. |
Reordering
Windows | MAC | To do this |
---|---|---|
Ctrl + left arrow or right arrow | Command + left arrow or right arrow | Reorders the focused header column to the left or right position. |
Sorting
Windows | MAC | To do this |
---|---|---|
Enter | Enter | Applies sorting (ascending/descending) to the focused column header. |
Ctrl + Enter | Command + Enter | Adds the focused column to multi-column sorting while preserving existing sort criteria. |
Shift + Enter | Shift + Enter | Removes sorting from the focused header column. |
- The Command and Control keys on Mac devices can be interchanged. When this switch occurs, use the Command key in place of the Control key and the Control key in place of the Command key for the above listed key interactions with Mac devices. For example, after switching the keys to group the columns when the header element is focused use Command + Space and for expanding the visible groups use Ctrl + Down Arrow.
How to prevent default key action behavior
The Syncfusion Angular Grid provides flexibility to prevent default key action behaviors based on application requirements. This capability allows you to intercept and customize responses when specific keys are pressed within the grid.
To prevent default key action behavior in the grid, utilize the keyPressed event. This event triggers for every key press, enabling customization based on the pressed key.
The following example demonstrates how to prevent the default behavior of the “ENTER” key using the keyPressed
event.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, PageService, SortService, FilterService } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { data } from './datasource';
import {KeyboardEventArgs} from '@syncfusion/ej2-angular-grids';
@Component({
imports: [
GridModule
],
providers: [PageService, SortService, FilterService],
standalone: true,
selector: 'app-root',
template: `<ejs-grid [dataSource]='data' (keyPressed)="keyPressed($event)">
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' width=120></e-column>
<e-column field='CustomerID' headerText='Customer ID' width=150></e-column>
<e-column field='ShipCity' headerText='Ship City' width=150></e-column>
<e-column field='ShipName' headerText='Ship Name' width=150></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
ngOnInit(): void {
this.data = data;
}
keyPressed(args : KeyboardEventArgs) {
if (args.keyCode === 13) {
// Prevent the default Enter key action
args.cancel = true;
}
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Custom shortcut keys to perform grid actions
The Syncfusion Angular Grid component enables enhanced keyboard shortcut usability for various grid actions and navigation. Beyond built-in keyboard navigation capabilities, you can implement custom keyboard shortcuts to execute specific actions.
To achieve this, utilize the keyPressed event. This event triggers for every key press, enabling behavior customization based on the pressed key.
The following example demonstrates how to perform grid actions using shortcut keys through the keyPressed
event. Within the event, define the following custom shortcuts to perform various grid actions:
- Pressing N adds a new record.
- Pressing Ctrl + S saves a record by invoking endEdit.
- Pressing Ctrl + D deletes a record.
- Pressing Ctrl + A selects all rows.
- Pressing Ctrl + G groups the grid by a specified column.
The example also prevents default actions for the following keyboard shortcuts typically used for built-in grouping and editing:
- Ctrl + Space
- Insert
- F2
- Delete
- Enter
You can add more custom shortcuts and actions as needed to enhance the functionality of your Syncfusion Angular Grid component.
import { NgModule } from '@angular/core'
import { FormsModule } from '@angular/forms'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule, EditService, ToolbarService, GroupService } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit, ViewChild } from '@angular/core';
import { cascadeData } from './datasource';
import { EditSettingsModel, ToolbarItems, GridComponent, SelectionSettingsModel, KeyboardEventArgs } from '@syncfusion/ej2-angular-grids';
@Component({
imports: [
GridModule,
FormsModule,
],
providers: [EditService, ToolbarService, GroupService],
standalone: true,
selector: 'app-root',
template: `<ejs-grid #grid [dataSource]='data' (keyPressed)="keyPressed($event)" [editSettings]='editSettings' [toolbar]='toolbar' height='273px' allowGrouping="true" [selectionSettings]='selectionOptions' >
<e-columns>
<e-column field='OrderID' headerText='Order ID' textAlign='Right' isPrimaryKey='true' width=100></e-column>
<e-column field='CustomerID' headerText='Customer ID' width=120></e-column>
<e-column field='ShipCountry' headerText='Ship Country' width=150></e-column>
</e-columns>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
public editSettings?: EditSettingsModel;
public toolbar?: ToolbarItems[];
public selectionOptions?: SelectionSettingsModel;
@ViewChild('grid') grid?: GridComponent;
keyPressed(e: KeyboardEventArgs) {
const key = e.key.toLowerCase();
switch (key) {
case 'n':
e.preventDefault();
(this.grid as GridComponent).addRecord();
break;
case 's':
if (e.ctrlKey) {
e.preventDefault();
(this.grid as GridComponent).endEdit();
}
break;
case 'd':
if (e.ctrlKey) {
e.preventDefault();
(this.grid as GridComponent).deleteRecord();
}
break;
case 'a':
if (e.ctrlKey) {
e.preventDefault();
(this.grid as GridComponent).selectRowsByRange(0);
}
break;
case 'g':
if (e.ctrlKey) {
e.preventDefault();
(this.grid as GridComponent).groupColumn('CustomerID');
}
break;
case 'enter':
e.preventDefault();
e.cancel = true;
(this.grid as GridComponent).refreshColumns();
break;
case 'insert':
e.preventDefault();
e.cancel = true;
break;
case 'delete':
e.preventDefault();
e.cancel = true;
break;
case 'f2':
e.preventDefault();
e.cancel = true;
break;
case '" "':
if (e.ctrlKey) {
e.preventDefault();
e.cancel = true;
}
break;
// Add more custom shortcuts as needed
}
}
ngOnInit(): void {
this.data = cascadeData;
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true };
this.toolbar = ['Add', 'Edit', 'Delete', 'Update', 'Cancel'];
this.selectionOptions = {
type: 'Multiple',
};
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));
Ensuring accessibility
The Grid component’s accessibility levels are ensured through an accessibility-checker and axe-core software tools during automated testing.
The accessibility compliance of the Grid component is shown in the following sample. Open the sample in a new window to evaluate the accessibility of the Grid component with accessibility tools.
import { NgModule } from '@angular/core'
import { BrowserModule } from '@angular/platform-browser'
import { GridModule } from '@syncfusion/ej2-angular-grids'
import { PageService, SortService, ReorderService, FilterService, GroupService, ColumnChooserService,
AggregateService, ToolbarService, SelectionService, RowDDService, } from '@syncfusion/ej2-angular-grids'
import { Component, OnInit } from '@angular/core';
import { data } from './datasource';
import { PageSettingsModel, ToolbarItems, SearchSettingsModel, SelectionSettingsModel,
FilterSettingsModel, GroupSettingsModel, EditSettingsModel, SortSettingsModel } from '@syncfusion/ej2-angular-grids';
@Component({
imports: [
GridModule
],
providers: [PageService,
SortService,
ReorderService,
FilterService,
GroupService,
AggregateService,
ToolbarService,
SelectionService,
RowDDService,
ColumnChooserService ],
standalone: true,
selector: 'app-root',
template: `
<ejs-grid [dataSource]='data' [allowPaging]="true" [pageSettings]="pageSettings"
[searchSettings]='searchOptions' [toolbar]='toolbarOptions' [allowReordering]='true' [allowSorting]="true"
[allowReordering]='true' [allowRowDragAndDrop]='true' [selectionSettings]='selectionOptions' [selectedRowIndex]='6' [allowSorting]="true" [sortSettings]='sortOptions'
[allowFiltering]="true" [filterSettings]='filterOptions' [allowGrouping]="true" [groupSettings]='groupOptions' [editSettings]='editSettings' [showColumnChooser]= 'true'>
<e-columns>
<e-column type="checkbox" width=50></e-column>
<e-column field='OrderID' headerText='Order ID' isPrimaryKey='true' textAlign='Right' width=90></e-column>
<e-column field='CustomerID' headerText='Customer ID' width=120></e-column>
<e-column field='OrderDate' headerText='Order Date' textAlign='Right' format='yMd' width=120></e-column>
<e-column field='Freight' headerText='Freight($)' textAlign='Right' format='C2' width=90></e-column>
<e-column field='ShipCity' headerText='Ship City' width=150></e-column>
<e-column field='ShipCountry' headerText='Ship Country' width=140></e-column>
<e-column field='ShipName' headerText='Shipped Name' textAlign='Right' width=140></e-column>
</e-columns>
<e-aggregates>
<e-aggregate>
<e-columns>
<e-column field="Freight" type="sum">
<ng-template #footerTemplate let-data>Sum: {{data.sum}} </ng-template>
</e-column>
</e-columns>
</e-aggregate>
<e-aggregate>
<e-columns>
<e-column field="Freight" type="sum">
<ng-template #groupFooterTemplate let-data>Sum: {{data.sum}} </ng-template>
</e-column>
</e-columns>
</e-aggregate>
<e-aggregate>
<e-columns>
<e-column field="Freight" type="max">
<ng-template #groupCaptionTemplate let-data>Max: {{data.max}}</ng-template>
</e-column>
</e-columns>
</e-aggregate>
</e-aggregates>
</ejs-grid>`
})
export class AppComponent implements OnInit {
public data?: object[];
public pageSettings?: PageSettingsModel;
public toolbarOptions?: ToolbarItems[];
public searchOptions?: SearchSettingsModel;
public selectionOptions?: SelectionSettingsModel;
public sortOptions?: SortSettingsModel;
public filterOptions?: FilterSettingsModel;
public groupOptions?: GroupSettingsModel;
public editSettings?: EditSettingsModel;
ngOnInit(): void {
this.data = data;
this.pageSettings = { pageCount: 2, pageSizes: true };
this.searchOptions = { fields: ['ShipCountry'], operator: 'contains', key: 'a', ignoreCase: true };
this.toolbarOptions = ['Add', 'Edit', 'Delete', 'Update', 'Cancel', 'Search', 'ColumnChooser'];
this.selectionOptions = { type: 'Multiple', mode: 'Both' };
this.sortOptions = { columns: [{ field: 'OrderID', direction: 'Ascending' }, { field: 'ShipCity', direction: 'Descending' }] };
this.filterOptions = {type:'Excel'};
this.groupOptions = { columns: ['CustomerID'] };
this.editSettings = { allowEditing: true, allowAdding: true, allowDeleting: true, };
}
}
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import 'zone.js';
bootstrapApplication(AppComponent).catch((err) => console.error(err));