How can I help you?
Accessibility in Angular Grid Component
19 Mar 202624 minutes to read
The Syncfusion® Angular Grid component follows major accessibility guidelines and standards, including the Americans with Disabilities Act (ADA), Section 508, WCAG 2.2, and WAI‑ARIA roles. These standards ensure the grid is usable with assistive technologies and keyboard‑only navigation.
The accessibility compliance for the Grid component is outlined below.
- All features of the component meet the requirement.
- Some features of the component do not meet the requirement.
- The component does not meet the requirement.WAI-ARIA attributes
The Angular Grid follows the WAI-ARIA grid pattern to ensure compatibility with assistive technologies. The following attributes and roles are used throughout the component:
| Attribute / Role | Purpose |
|---|---|
role=grid |
Identifies the container element of the grid. |
role=row |
Represents a row containing grid cells. |
role=rowgroup |
Represents a logical grouping of rows. |
role=columnheader |
Identifies header cells that describe a column. |
role=gridcell |
Defines an individual grid cell. |
role=button |
Represents button elements inside the grid. |
role=search |
Identifies a search region, the toolbar search control. |
role=presentation |
Indicates elements that are ignored by assistive technologies (used for layout-only elements). |
role=navigation |
Identifies the pager navigation region. |
aria-colindex |
Defines the column index relative to total columns. |
aria-rowindex |
Defines the row index relative to total rows. |
aria-rowspan |
Indicates how many rows a cell spans. |
aria-colspan |
Indicates how many columns a cell spans. |
aria-rowcount |
Specifies the total number of rows. |
aria-colcount |
Specifies the total number of columns. |
aria-selected |
Indicates the selection state of a row or cell. |
aria-expanded |
Indicates the expanded or collapsed state in hierarchical grids. |
aria-sort |
Indicates ascending or descending sort order. |
aria-busy |
Indicates that an element is being updated. |
aria-owns |
Defines contextual relationships between parent and child elements. |
aria-hidden |
Hides elements from assistive technologies. |
aria-labelledby |
Provides an accessible name for specific elements such as filter dialog items. |
aria-describedby |
Provides descriptive help text for focused header cells. |
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 highlight 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 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 provides keyboard navigation and follows WAI‑ARIA keyboard interaction guidelines. Some keyboard behaviors vary depending on which features are enabled; consult the compatibility table above and the examples below for specific behavior.
Pager
| Windows | MAC | Description |
|---|---|---|
| Tab | Tab | Focus the next pager item. |
| Shift + Tab | Shift + Tab | Focus the previous pager item. |
| Enter / Space | Enter / Space | Select the focused page. |
| PageUp / Left Arrow | Left Arrow | Navigate to the previous page. |
| PageDown / Right Arrow | Right Arrow | Navigate to the next page. |
| Home / Ctrl + Alt + PageUp | Fn + Left Arrow | Navigate to the first page. |
| End / Ctrl + Alt + PageDown | Fn + Right Arrow | Navigate to the last page. |
Focus Elements
| Windows | MAC | To do this |
|---|---|---|
| Home | Fn + Left Arrow | Shifts the focus to the first cell in the currently focused row. |
| End | Fn + Right Arrow | Shifts the focus to the last cell in the currently focused row. |
| Ctrl + Home | Command + Fn + Left Arrow | Shifts the focus to the first cell of the first row within the grid. |
| Ctrl + End | Command + Fn + Right Arrow | Shifts the focus to the last cell of the last row within the grid. |
| Up Arrow | Up Arrow | Moves the cell focus upward from the current cell. |
| Down Arrow | Down Arrow | Moves the cell focus downward from the current cell. |
| Right Arrow | Right Arrow | Moves the cell focus to the right of the current cell. |
| Left Arrow | Left Arrow | Moves the cell focus to the left of the current cell. |
| Alt + J | Alt + J | Moves the focus to the entire grid. |
| Alt + W | Alt + W | Moves the focus to the grid content element. |
Selection
| Windows | MAC | To do this |
|---|---|---|
| Up Arrow | Up Arrow | Moves the selection up by one row or cell from the current position. |
| Down Arrow | Down Arrow | Moves the selection down by one row or cell from the current position. |
| Right Arrow | Right Arrow | Moves the selection one cell to the right from the current cell. |
| Left Arrow | Left Arrow | Moves the selection one cell to the left from the current cell. |
| Shift + Up Arrow | Shift + Up Arrow | Extends the selection upward by rows or cells from the current selection. |
| Shift + Down Arrow | Shift + Down Arrow | Extends the selection downward by rows or cells from the current selection. |
| Shift + Right Arrow | Shift + Right Arrow | Extends the selection to the right from the current cell. |
| Shift + Left Arrow | Shift + Left Arrow | Extends the selection to the left from the current cell. |
| Enter | Enter | Moves the selection down by one row or cell. |
| Shift + Enter | Shift + Enter | Moves the selection up by one row or cell. |
| Esc | Esc | Clears all current selections. |
| Ctrl + A | Ctrl + A | Selects all rows or cells on the current page. |
Grouping
| Windows | MAC | To do this |
|---|---|---|
| Ctrl + Up Arrow | Command + Up Arrow | Collapses all visible groups. |
| Ctrl + Down Arrow | Command + Down Arrow | Expands all visible groups. |
| Ctrl + Space | Ctrl + Space | Groups items when the header element is focused. |
| Enter | Enter | Expands or collapses the current group, detail row, or child grid if the active cell controls this function. |
| Windows | MAC | To do this |
|---|---|---|
| Ctrl + P | Command + P | Prints the Grid. |
Clipboard
| Windows | MAC | To do this |
|---|---|---|
| Ctrl + C | Command + C | Copies the data of selected rows or cells to the clipboard. |
| Ctrl + Shift + H | Ctrl + Shift + H | Copies the data of selected rows or cells along with the header to the clipboard. |
Editing
| Windows | MAC | To do this |
|---|---|---|
| F2 | F2 | Begins editing the selected row when Mode is Normal or Dialog, or begins editing the selected cell when Mode is Batch. |
| Enter | Enter | Saves the current form if Mode is Normal or Dialog; saves the current cell and begins editing the next row cell if Mode is Batch. |
| Insert | Ctrl + Command + Enter | Creates a new add form based on the NewRowPosition. |
| Delete | Delete | Removes the currently selected record. |
| Tab | Tab | Moves to the next editable cell if Mode is Normal or Dialog; saves the current cell and begins editing the next cell if Mode is Batch. |
| Shift + Tab | Shift + Tab | Moves to the previous editable cell if Mode is Normal or Dialog; saves the current cell and begins editing the previous cell if Mode is Batch. |
| Shift + Enter | Shift + Enter | Saves the current cell and begins editing the previous row cell when Mode is Batch. |
Filtering
| Windows | MAC | To do this |
|---|---|---|
| Alt + Down arrow | Alt + Down arrow | Opens the filter menu (Excel, menu, and checkbox filter) when the header element is focused. |
Column Menu
| Windows | MAC | To do this |
|---|---|---|
| Alt + Down arrow | Alt + Down arrow | Opens the column menu when the header element is focused. |
| Windows | MAC | To do this |
|---|---|---|
| Ctrl + left arrow or right arrow | Command + left arrow or right arrow | Moves the selected header column to the left or right. |
| Windows | Mac | Action |
|---|---|---|
| Enter | Enter | Applies sorting (cycles through ascending → descending → none) on the focused column. |
| Ctrl + Enter | Command + Enter | Adds the focused column to multi-sorting. |
| Shift + Enter | Shift + Enter | Removes sorting from the focused 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.
Preventing Default Key Actions
The Syncfusion® Angular Grid provides the capability to disable the default key action behavior according to application needs. This allows the application to intercept and modify the response when specific keys are pressed within the web interface.
To disable the default key action in the grid, use the keyPressed event.
import { data } from './datasource';
import { Component, OnInit } from '@angular/core';
import { FilterService, GridModule, KeyboardEventArgs, PageService, SortService } 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 allows improving the usability of keyboard shortcuts for various grid actions and navigation.
Besides the built-in keyboard navigation features, custom keyboard shortcuts can be created to perform specific tasks.
Use the keyPressed event of the grid to achieve this. This event triggers on every key press, enabling customization of the response according to the key pressed.
The example below demonstrates using shortcut keys to execute grid actions via the keyPressed event. Define the following custom shortcuts within the event to execute different grid actions:
- Pressing N adds a new record.
- Pressing Ctrl + S saves a record by calling
endEdit. - Pressing Ctrl + D deletes a record.
- Pressing Ctrl + A selects all rows.
- Pressing Ctrl + G groups the grid by a selected column.
Additionally, the default actions for these keyboard shortcuts related to grouping and editing are prevented:
- Ctrl + Space
- Insert
- F2
- Delete
- Enter
Add further custom shortcuts and actions as required to enhance the capabilities of the Syncfusion® Angular Grid component.
import { cascadeData } from './datasource';
import { Component, OnInit, ViewChild } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { EditService, EditSettingsModel, GridComponent, GridModule, GroupService, KeyboardEventArgs, SelectionSettingsModel, ToolbarItems, ToolbarService } 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='247px' 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 { Component, OnInit } from '@angular/core';
import { data } from './datasource';
import { PageSettingsModel, ToolbarItems, SearchSettingsModel,SelectionSettingsModel,GridModule, PageService, SortService, ReorderService, FilterService, GroupService, ColumnChooserService,
AggregateService, ToolbarService, SelectionService, RowDDService,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));