HelpBot Assistant

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.

Accessibility Criteria Compatibility
WCAG 2.2 Support Intermediate
Section 508 Support Intermediate
Screen Reader Support Yes
Right-To-Left Support Yes
Color Contrast Yes
Mobile Device Support Yes
Keyboard Navigation Support Intermediate
Accessibility Checker Validation Intermediate
Axe-core Accessibility Validation Intermediate
Yes - All features of the component meet the requirement.
Intermediate - Some features of the component do not meet the requirement.
No - 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.

Print

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));

See also

Accessibility in Syncfusion Angular components