---
title: "React Data Grid Documentation & API"
description: Create super-fast, responsive React Data Grids and tables with Ignite UI for React. Supports editing, filtering, data binding and many more. Try it now!
keywords: "React, Ignite UI for React, Infragistics, Getting Started, Grid"
license: commercial
mentionedTypes: ["Grid", "Column", "Cell", "CellTemplateContext", "GridRowComponent", "GridToolbar", "Paginator"]
namespace: Infragistics.Controls
---

# React Data Grid Documentation

<div class="sample-content">
    <article class="sample-column">
        <div class="tabbar-wrapper">
            <p>The [React Data Grid](https://www.infragistics.com/products/react-data-grid) component is used for displaying large volumes of data. Modern and more complex grids ensure smooth UX and bring an array of features for manipulating tabular data. There is an intuitive API, theming, branding, filtering, sorting, data selection, Excel-style filtering, and many more.</p>
            <p>The Ignite UI for React Data Table / Data Grid is a tabular React grid component that allows you to quickly bind and display your data with little coding or configuration. Features of the React data grid in our toolbox include filtering, sorting, templates, row selection, row grouping, row pinning, movable columns, virtualization, Master-Detail, and much more.</p>
            <p>The React tables are optimized for speed and performance, with the ability to handle millions of rows and columns, and real-time updates in an instant.</p>
        </div>
    </article>
    <article class="sample-column">
        <div class="tabbar-wrapper">
            <div class="tab-content">
                <Image src={landingGridPage} alt="React Data Grid" class="b-lazy responsive-img" />
            </div>
        </div>
    </article>
</div>

## React Data Grid Example

In this Ignite UI for React Grid example, you can see how users can do both basic and excel-style filtering, live-data sorting, and use grid summaries as well as cell templating. The demo also includes paging set to display 10 items per page.

<div class="divider--half"></div>

## Getting Started with React Data Grid

### Dependencies

To get started with the React Data Grid, first you need to install the `igniteui-react` and `igniteui-react-grids` packages.

```cmd
npm install --save igniteui-react
npm install --save igniteui-react-grids
```

You also need to include the following import to use the grid:

```tsx
```

The corresponding styles should also be referenced. You can choose light or dark option for one of the [themes](../themes/overview.md) and based on your project configuration to import it:

```tsx
import 'igniteui-react-grids/grids/themes/light/bootstrap.css'
```

For more details on how to customize the appearance of the grid, you may have a look at the [styling](data-grid.md#styling-react-grid) section.

## Usage

Now that we have the grid packages imported, let’s get started with the basic configuration and bind to local data:

```tsx
<IgrGrid id="grid1" autoGenerate={true} data={localData}></IgrGrid>
```

The property is a string value and is the unique identifier of the grid which will be auto-generated if not provided, while binds the grid, in this case to local data.

The property tells the grid to auto generate the grid's components based on the data source fields. It will also try to deduce the appropriate data type for the column if possible. Otherwise, the developer needs to explicitly define the columns and the mapping to the data source fields.

## Editable React Grid

Each operation for grid editing includes batch operations, meaning the API gives you the option to group edits into a single server call, or you can perform grid edit / update operations as they occur with grid interactions. Along with a great developer experience as an editable grid with CRUD operations, the grid includes Excel-like keyboard navigation. Common default grid navigation is included, plus the option to override any navigation option to meet the needs of your customers. An editable grid in with a great navigation scheme is critical to any modern line of business application, with the Ignite UI grid we make it easy.

Following this topic you will learn more about [cell template](data-grid.md#cell-template) and [cell editing template](data-grid.md#cell-editing-template) and editing.

## Grid Column Configuration

is used to define the grid's columns collection and to enable features per column like **sorting** and **filtering**. Cell, header, and footer templates are also available.

### Defining Columns

Let's turn the property off and define the columns collection in the markup:

```tsx
<IgrGrid id="grid1" autoGenerate={false} allowFiltering={true} data={localData}>
    <IgrColumn field="Name" sortable={true}></igc-column>
    <IgrColumn field="AthleteNumber" header="Athlete number" filterable={false} sortable={true}></IgrColumn>
    <IgrColumn field="TrackProgress" header="Track progress" filterable={false}></IgrColumn>
</IgrGrid>
```

### Header Template

The header template can be set to modify the column headers. The snippets below show you how to format the header text to upper case.

```tsx
function nameHeaderTemplate(ctx: IgrColumnTemplateContext) {
    return (
        <>
            {formatUppercase(ctx.column.field)}
        </>
    );
}

function formatUppercase(value: string) {
    return value.toUpperCase();
}

<IgrColumn field="Name" headerTemplate={nameHeaderTemplate}></IgrColumn>
```

### Cell Template

When cell template is set it changes all the cells in the column. The context object provided in the template consists of the cell value provided implicitly and the cell object itself. It can be used to define a template where the cells' text could be formatted e.g. as title case.

```tsx
function formatTitleCase(value: string) {
    return value.toUpperCase();
}

function nameCellTemplate(ctx: IgrCellTemplateContext) {
    return (
        <>
            {formatTitleCase(ctx.implicit)}
        </>
    );
}

<IgrColumn field="Name" bodyTemplate={nameCellTemplate}></IgrColumn>
```

In the snippet above we take a reference to the implicitly provided cell value. This is sufficient if you just want to present some data and maybe apply some custom styling or pipe transforms over the value of the cell. However even more useful is to take the instance itself as shown below:

```tsx
function nameCellTemplate(ctx: IgrCellTemplateContext) {
    return (
        <>
            <span tabIndex={0} onClick={() => deleteRow(ctx.cell.id.rowID)}>
                {formatTitleCase(ctx.cell.value)}
            </span>
        </>
    );
}

function subscriptionCellTemplate(ctx: IgrCellTemplateContext) {
    if (ctx.cell.value) {
            return (
                <>
                <input type="checkbox" checked />
                </>
            );
    } else {
            return (
                <>
                <input type="checkbox"/>
                </>
            );
    }
}

function deleteRow(rowID: any) {
    grid.current.deleteRow(rowID);
}

function formatTitleCase(value: string) {
    return value.toUpperCase();
}

<IgrGrid id="grid" ref={grid} autoGenerate={false} data={data} primaryKey="Name">
    <IgrColumn field="Name" dataType="string" bodyTemplate={nameCellTemplate}></IgrColumn>
    <IgrColumn field="Subscription" dataType="boolean" bodyTemplate={subscriptionCellTemplate}></IgrColumn>
</IgrGrid>
```

> **Note**:
> The grid exposes a default handling for number, string, date and boolean column types. For example, the column will display `check` or `close` icon, instead of true/false by default, for boolean column type.

When properly implemented, the cell editing template also ensures that the cell's will correctly pass through the grid [editing event cycle](grid/editing.md#event-arguments-and-sequence).

### Cell Editing Template

The column also accepts one last template that will be used when a cell is in edit mode. As with the other column templates, the provided context object is again the cell value and the cell object itself. Of course in order to make the edit-mode template accessible to end users, you need
to set the property of the column to true.

```tsx
function priceCellTemplate(ctx: IgrCellTemplateContext) {
    return (
        <>
            <label>
                Enter the new price tag
            </label>
            <input name="price" type="number" value={ctx.cell.value}
                onChange={() => updateValue(ctx.cell.value)}/>
        </>
    );
}

function updateValue(value: number) {
  // Custom update code
}

<IgrColumn field="Price" dataType="number" editable={true} inlineEditorTemplate={priceCellTemplate}></IgrColumn>
```

Make sure to check the API for the in order to get accustomed with the provided properties you can use in your templates.

### Column Template API

Each of the column templates can be changed programmatically at any point through the object itself. For example in the code below, we have declared two templates for our user data. In our TypeScript code we'll get references to the templates themselves and then based on some condition we will render the appropriate template for the column in our application.

```tsx
<IgrGrid ref={grid}>
    {/* Column declarations */}
</IgrGrid>
```

```tsx
function normalViewTemplate(ctx: IgrCellTemplateContext) {
    return (
        <>
            <div className="user-details">{ ctx.cell.value }</div>
            <UserDetailsComponent></UserDetailsComponent>
        </>
    );
}

function smallViewTemplate(ctx: IgrCellTemplateContext) {
    return (
        <>
            <div className="user-details-small">{ ctx.cell.value }</div>
        </>
    );
}

const column = grid.current.getColumnByName("User");
// Return the appropriate template based on some condition.
// For example saved user settings, viewport size, etc.
column.bodyTemplate = smallViewTemplate;
```

Column properties can also be set in code in the `ColumnInit` event which is emitted when the columns are initialized in the grid.

```tsx
function initColumns(event: CustomEvent<IgrColumn>) {
    const column: IgrColumn = event.detail;
    if (column.field === 'ProductName') {
        column.sortable = true;
        column.editable = true;
    }
}

<IgrGrid onColumnInit={initColumns} />
```

The code above will make the **ProductName** column sortable and editable and will instantiate the corresponding features UI (like inputs for editing, etc.).

### Custom Display Format

There are optional parameters for formatting:

- - determines what date/time parts are displayed, defaults to `'mediumDate'`, equivalent to **'MMM d, y'**
- - the timezone offset for dates. By default uses the end-user's local system timezone
- - decimal representation objects. Default to **1.0-3**

To allow customizing the display format by these parameters, the input is exposed. A column will respect only the corresponding properties for its data type, if is set. Example:

```tsx
const columnPipeArgs: IgrColumnPipeArgs = {
    format: "longDate",
    timezone: "UTC",
    digitsInfo: "1.2-2"
};

<IgrColumn field="OrderDate" dataType="date" pipeArgs={columnPipeArgs}></IgrColumn>
```

The `OrderDate` column will respect only the and properties, while the `UnitPrice` will only respect the .

All available column data types could be found in the official [Column types topic](grid/column-types.md#default-template).

## Grid Data Structure

The handles **flat data** and nested **POJO (Plain old Java objects)**. The data structure specific for rendering is in the form:

```typescript
const OBJECT_ARRAY = [{
        ObjectKey1: value1,
        ObjectKey2: value2,
        // ...
        ObjectKeyN: valueN
    },
    // ...
  }];

const POJO = [{
        ObjectKey1: value1,
        ObjectKey2: value2,
        // ...
        ObjectKeyN: {
          ObjectKeyN1: value1,
          ObjectKeyN2: value2,
          // ...
          ObjectKeyNM: valueNM,
        }
    },
    // ...
  }];
```

>**WARNING**:
>**The key values must not contain arrays**.

>If you use columns **the data keys must be identical.**

## Grid Data Binding

Our React Data Grid provides unmatched data binding options and is optimized for real-time updates and smooth scrolling. With low-latency rendering, the grid ensures any UI change is displayed in an instant, including live streaming data, large datasets, and more.

Before going any further with the React Data Grid we want to change the grid to bind to remote data service, which is the common scenario in large-scale applications.

You can do this by fetching the data from a given url receiving a JSON response and assigning it to the grid's property that is used as the grid's data source:

```tsx
<IgrGrid ref={grid} data={data}></IgrGrid>
```

```tsx
const [data, setData] = useState<any[]>([]);

function fetchData(url: string): void {
    fetch(url)
      .then(response => response.json())
      .then(data => setData(data));
}
```

**Note**: The grid property is best to be avoided when binding to remote data for now. It assumes that the data is available in order to inspect it and generate the appropriate columns. This is usually not the case until the remote service responds, and the grid will throw an error. Making available, when binding to remote service, is on our roadmap for future versions.

## Complex Data Binding

Complex Data Binding allows for seamless interaction with multi-level data, complex, real-world datasets, object-oriented data modules, etc. Using our React Data Grid, you can easily bind to complex objects (including data structures that nest deeper than one level). This happens through a path of properties in the data record.

Take a look at the following data model:

```typescript
interface AminoAcid {
    name: string;
    abbreviation: {
        short: string;
        long: string;
    }
    weight: {
        molecular: number;
        residue: number;
    },
    formula: {
        molecular: string;
        residue: string;
    }
}
```

For example, in order to display the weights of a given amino acid in the grid the following snippet will suffice

```tsx
<IgrColumn field="weight.molecular"></IgrColumn>
<IgrColumn field="weight.residue"></IgrColumn>
```

An alternative way to bind complex data, or to visualize composite data (from more than one column) in the is to use a custom body template for the column. Generally, one can:

- use the `value` of the cell, that contains the nested data

- use the `cell` object in the template, from which to access the `ctx.cell.id.rowIndex` or `ctx.cell.id.rowID` to get the row via the grid's API and retrieve any value from it and interpolate those in the template.

```tsx
function getName(rowIndex: number) {
    return grid.current.getRowByIndex(rowIndex).data["Name"];
}
function getWeight(rowIndex: number) {
    return grid.current.getRowByIndex(rowIndex).data["weight"]["molecular"];
}

function abbreviationLongCellTemplate(ctx: IgrCellTemplateContext) {
    return (
        <>
            <div>
            <div>
                { ctx.cell.value }
                    {getName(ctx.cell.id.rowIndex)}
                    {getWeight(ctx.cell.id.rowIndex)}
            </div>
        </div>
        </>
    )
}

<IgrColumn field="abbreviation.long" bodyTemplate={abbreviationLongCellTemplate}></IgrColumn>
```

Here is an example on how body template is used to display complex data. Below is the data that we are going to use:

```typescript
export const EMPLOYEE_DATA = [
    {
        Age: 55,
        Employees: [
            {
                Age: 43,
                HireDate: new Date(2011, 6, 3),
                ID: 3,
                Name: "Michael Burke",
                Title: "Senior Software Developer"
            },
            {
                Age: 29,
                HireDate: new Date(2009, 6, 19),
                ID: 2,
                Name: "Thomas Anderson",
                Title: "Senior Software Developer"
            },
            {
                Age: 31,
                HireDate: new Date(2014, 8, 18),
                ID: 11,
                Name: "Monica Reyes",
                Title: "Software Development Team Lead"
            },
            {
                Age: 35,
                HireDate: new Date(2015, 9, 17),
                ID: 6,
                Name: "Roland Mendel",
                Title: "Senior Software Developer"
            }],
        HireDate: new Date(2008, 3, 20),
        ID: 1,
        Name: "John Winchester",
        Title: "Development Manager"
    }
]
```

The custom template for the column, that will render the nested data:

```tsx
function addressCellTemplate(ctx: IgrCellTemplateContext) {
    if (ctx.cell.value != null) {
        if (ctx.cell.value.length === 0) return <></>;
        const value = ctx.cell.value[0];
        return (
          <>
              <IgrExpansionPanel>
                  <div slot="title" style={{fontSize: "1.1em", fontWeight: "bold", marginTop: "1rem", marginBottom: "0.25rem"}}>
                      {value.Name}
                  </div>
                  <div className="description">
                      <IgrInput type="text" label="Title" name="title" value={value.Title} style={{textOverflow: "ellipsis"}}
                          onInput={(e: CustomEvent<string>) => {
                              ctx.cell.value[0][e.target.label] = e.detail;
                              grid.current.markForCheck();
                          }} />
                      <IgrInput type="number" label="Age" name="title" value={value.Age} style={{textOverflow: "ellipsis"}}
                          onInput={(e: CustomEvent<string>) => {
                              ctx.cell.value[0][e.target.label] = e.detail;
                              grid.current.markForCheck();
                          }} />
                  </div>
              </IgrExpansionPanel>
          </>
        );
    }
    return <></>;
}

<IgrColumn field="Employees" header="Employees" width="40%" bodyTemplate={addressCellTemplate}></IgrColumn>
```

And the result from this configuration is:

### Working with Flat Data Overview

The flat data binding approach is similar to the one that we already described above, but instead of **cell value** we are going to use the property of the .

Since the React grid is a component for **rendering**, **manipulating** and **preserving** data records, having access to **every data record** gives you the opportunity to customize the approach of handling it. The `data` property provides you this opportunity.

Below is the data that we are going to use:

```typescript
export const DATA: any[] = [
    {
        Address: "Obere Str. 57",
        City: "Berlin",
        CompanyName: "Alfreds Futterkiste",
        ContactName: "Maria Anders",
        ContactTitle: "Sales Representative",
        Country: "Germany",
        Fax: "030-0076545",
        ID: "ALFKI",
        Phone: "030-0074321",
        PostalCode: "12209",
        Region: null
    }
]
```

The custom template:

```tsx
function getCountry(rowIndex: number) {
    return grid.current.getRowByIndex(rowIndex).data["Country"];
}

function getCity(rowIndex: number) {
     return grid.current.getRowByIndex(rowIndex).data["City"];
}

function getPostalCode(rowIndex: number) {
     return grid.current.getRowByIndex(rowIndex).data["PostalCode"];
}

function addressCellTemplate(ctx: IgrCellTemplateContext) {
    var cell: IgrCellType = ctx.cell;
    if (cell === undefined || cell.row === undefined || cell.row.data === undefined) {
        return <></>;
    }

    return (
        <>
            <div className="address-container">
                <div className="country-city">
                    <span><strong>Country:</strong> {cell.row.data.Country}</span>
                    <br/>
                    <span><strong>City:</strong> {cell.row.data.City}</span>
                </div>
                <div className="phone-pscode">
                    <span><strong>Postal Code:</strong> {cell.row.data.PostalCode}</span>
                    <br/>
                    <span><strong>Phone:</strong> {cell.row.data.Phone}</span>
                </div>
                <br />
            </div>
        </>
    );
}

<IgrColumn field="Address" header="Address" width="25%" editable={true} bodyTemplate={addressCellTemplate}></IgrColumn>
```

Keep in mind that with the above defined template you will not be able to make editing operations, so we need an editor template.

```tsx
function addressEditCellTemplate(ctx: IgrCellTemplateContext) {
    var cell: IgrCellType = ctx.cell;
    if (cell === undefined || cell.row === undefined || cell.row.data === undefined) {
        return <></>;
    }

    return (
        <>
            <div className="contact-container--edit" style={{padding: "1rem"}}>
                <IgrInput
                    label="Country"
                    onInput={(e: CustomEvent<string>) => cell.row.data.Country = e.detail}
                    value={cell.row.data.Country}
                ></IgrInput>
                <IgrInput
                    label="City"
                    onInput={(e: CustomEvent<string>) => cell.row.data.City = e.detail}
                    value={cell.row.data.City}
                ></IgrInput>
                <IgrInput
                    label="Postal Code"
                    onInput={(e: CustomEvent<string>) => cell.row.data.PostalCode = e.detail}
                    value={cell.row.data.PostalCode}
                ></IgrInput>
                <IgrInput
                    label="Phone"
                    onInput={(e: CustomEvent<string>) => cell.row.data.Phone = e.detail}
                    value={cell.row.data.Phone}
                ></IgrInput>
            </div>
        </>
    );
}

<IgrColumn field="Address" dataType="number" width="25%" editable={true} inlineEditorTemplate={addressEditCellTemplate}></IgrColumn>
```

### Working with Flat Data Example

Using code snippets from previous section will result in the following example of ## Keyboard Navigation

Keyboard navigation of the provides a rich variety of keyboard interactions for the user. It enhances accessibility and allows intuitive navigation through any type of elements inside (cell, row, column header, toolbar, footer, etc.).

{/* The sizing topic is still not available thus the Sizing section is commented out. _/}
{/_ ## Sizing

See the [Grid Sizing](sizing.md) topic. */}

## Styling React Grid
> **Note**:
> The grid uses **css grid layout**, which is **not supported in IE without prefixing**, consequently it will not render properly.

In addition to the predefined themes, the grid could be further customized by setting some of the available [CSS properties](../grids/theming-grid.md). In case you would like to change the header background and text color, you need to set a class for the grid first:

```tsx
<IgrGrid className="grid"></IgrGrid>
```

Then set the `--header-background` and `--header-text-color` CSS properties for that class:

```css
.grid {
    --header-background: #494949;
    --header-text-color: #FFF;
}
```

## Known Limitations

|Limitation|Description|
|--- |--- |
|Column widths set in `percentage` and `px`|Currently we do not support mixing of column widths with `%` and `px`.|
|When trying to filter a column of type `number`|If a value different than `number` is entered into the filtering input, `NaN` is returned due to an incorrect cast.|
|Grid `width` does not depend on the column widths | The `width` of all columns does not determine the spanning of the grid itself. It is determined by the parent container dimensions or the defined grid's `width`.|
|Grid nested in parent container | When grid's `width` is not set and it is placed in a parent container with defined dimensions, the grid spans to this container.|
| Columns have a minimum allowed column width. Depending on the `--ig-size` CSS variable, they are as follows: <br/>"small": 56px <br/> "medium": 64px <br/> "large ": 80px | If width less than the minimum allowed is set it will not affect the rendered elements. They will render with the minimum allowed width for the corresponding `--ig-size`. This may lead to an unexpected behavior with horizontal virtualization and is therefore not supported.
| Row height is not affected by the height of cells that are not currently rendered in view. | Because of virtualization a column with a custom template (that changes the cell height) that is not in the view will not affect the row height. The row height will be affected only while the related column is scrolled in the view.

## API References

<br />
<br />
<br />
<br />
<br />

<br />
<br />
<br />
<br />

## Theming Dependencies

- **Icon Theme**
- **InputGroup Theme**
- **Chip Theme**
- **Ripple Theme**
- **Button Theme**
- **Overlay Theme**
- **DropDown Theme**
- **Calendar Theme**
- **SnackBar Theme**
- **Badge Theme**

Our community is active and always welcoming to new ideas.

- [Ignite UI for React **Forums**](https://www.infragistics.com/community/forums/f/ignite-ui-for-react)
- [Ignite UI for React **GitHub**](https://github.com/IgniteUI/igniteui-react)
