Changing tab-index with DOM Manipulation in React
Tags: react, a11y, javascript, webdev
Published: 2023-06-14 18:30:47

Before we go through the DOM manipulation, let us understand 

**What is DOM?**
The Document Object Model (DOM) is the data representation of the objects that comprise the structure and content of a document on the web.
It is a programming interface for web documents. It represents the page so that programs can change the document structure, style, and content. The DOM represents the document as nodes and objects; that way, programming languages can interact with the page.

Now let us understand **Why need to change the tab-index?**

**Example:** Let us consider we have a Material UI DataGrid component

As per WCAG guidelines, _the table and its rows are generally not keyboard focusable because they're not interactive elements._

In the Material UI DataGrid component, first header column by default is keyboard focusable. 

<img width="100%" style="width:100%" src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExcnU1c2NyYXJ2c2d6YTV5eGNrMzY5b2ZwZmV1OW15MG0yMnp3d3R3NSZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/OLsDSMIu2Cja6ZLTMn/giphy.gif">

In such scenarios we might need to explicitly change the tabIndex to -1 in order to change the make the application meets the accessibility criteria.

You can better understand it with the following code:

```React
import { useEffect } from "react";
import { DataGrid } from "@mui/x-data-grid";
 ```

- First fetch the elements using document.querySelector() of which we need to change the tab-index. 
- document.querySelector() returns HTMLCollection as we have more than 1 element with class legend-color. 
- Store this HTMLCollection in a variable named headerCell.
- Finally, we loop through headerCell, thus assigning tabIndex = -1 to each header cell which needs to be non-focusable.

If you wonder why we use setTimeout() then let me answer that for you. It may be possible that DOM might not have already loaded by the time script run. Thus, setTimeout() will ensure that once all the code is executed then we change the tabIndex.

```React
const CustomDataGrid = () => {

useEffect(() => {
    setTimeout(() => {
        const headerCell = document.querySelector('legend-color')
        for(let i = 0; i < headerCell.length; i ++){
            headerCell[i].tabIndex = -1
        }
    }, 1000)
  }, [])
 
const columns = [
    {
        field: "id",
        headerName: "ID",
        headerClassName: "header-id"
    },
    {
        field: "firstName",
        headerName: "First name",
        headerClassName: "header-first-name"
    },
    {
        field: "lastName",
        headerName: "Last Name",
        headerClassName: "header-last-name"
    }
]
const rows = [
  { id: 1, firstName: "Harshita", lastName: "Gupta" },
  { id: 2, firstName: "Lannister", lastName: "Cersei" },
];

return (
<DataGrid 
    columns={columns}
    rows={rows}
  />
 )
}
```
**Final results**
Focus is removed from the first header column ID
<img width="100%" style="width:100%" src="https://media.giphy.com/media/v1.Y2lkPTc5MGI3NjExeWdqcGRqMW9ya3Y5YnN6cnpnZ2w5eWxzdHZlemd0ZHFmODJ3ZHNrNyZlcD12MV9pbnRlcm5hbF9naWZfYnlfaWQmY3Q9Zw/H2iWIz661vQzDxKubw/giphy.gif" />

Refer to the following sandbox for the code and implementation:
https://hctxgc.csb.app/

Hope this blog helped you.
Thanks 👩‍💻