---
name: DataGrid
menu: Components
---

import PropsTable from 'website-src/components/PropsTable'
import DataGrid from './DataGrid'
import SplitButton from '../SplitButton/SplitButton'
import ScreenSizeProvider from '../ScreenSizeProvider/ScreenSizeProvider'
import { livePreviewStyle } from '../helpers/constants'
import { LiveProvider, LiveEditor, LiveError, LivePreview } from 'react-live'

# DataGrid

The `DataGrid` is a wrapper for `Table` that allows you to easily define table columns using the API and provides sorting & pagination capabilities.

## Basic usage

The `DataGrid` component has several sub-components to help define your grid structure:
  - `DataGrid.TopSection` - A flex container to be rendered above the table. You can use this space to render other `DataGrid` components in whatever order you like.
    In the card view, `TopSection` will always include the sort buttons as the first element.
    You can use the `justifyContent` and `spacing` props to help with arranging elements and spacing them out from each other.
  - `DataGrid.BottomSection` - A flex container to be rendered below the table. You can use this space to render other `DataGrid` components in whatever order you like.
    You can use the `justifyContent` and `spacing` props to help with arranging elements and spacing them out from each other.
  - `DataGrid.Table` - A wrapper for our `Table` component which maps the data you pass to the columns that have been configured.
  - `DataGrid.Column` - Defines a column template that will be applied to the data passed to the table.
    Any extra props passed to `Column` will be passed on to `Table.Cell` internally.
  - `DataGrid.PageSizeSelect` - Renders a component that can be used to pick the number of rows per page.
  - `DataGrid.Pagination` - A wrapper for our `Pagination` component. This piece allows users to change pages. **Note:** when using this component, `pageCount` is required in `paginationOptions`.
  - `DataGrid.PrevNext` - A wrapper for our `PrevNext` component, which is a simpler form of pagination. This method of pagination does not require a `pageCount`.

### DataGrid.Column

The Column API is central to making a DataGrid. There are several options for controlling what data is rendered and how, as well as controlling the column header.

- `id`: the name of a property on the table data. Maps the value that will be rendered in each table cell; required if no render function or component is passed.
- `title`: the contents of the header cell.
- `sortable`: if true, the header cell will become a button that can be clicked to change the sort options; `id` and `title` are required on sortable columns.
- `order`: the order in which the columns should appear; default is React render order, so 99% of the time this can be left blank.
- `headerProps`: an object containing any extra props to be passed to the header cell
- `render`/children: a function to render the cell contents. The first argument is the current data row being processed, and the second is a CellInfo object (definition shown below).
- `as`: a component to use as the cell contents. It receives a `row` prop, as well as the `CellInfo` props.
- Any other props are passed directly to the `Table.Cell` component, e.g. `align`.

```
interface CellInfo {
  id?: string // from Column's `id` prop
  value?: any // mapped from `row[id]`
  rowIndex: number
  colIndex: number
}
```

## Best practices

- The `sortOptions` & `paginationOptions` props can be used either controlled or uncontrolled. If using them uncontrolled, the `onPagisort` handler can be used to update the data source whenever a change is made to either pagination _or_ sorting.
- `paginationOptions` can be passed as a single object to the `<DataGrid>` element, or as individual props to the relevant sub-components: `pageSize` to `PageSizeSelect`, `currentPage` & `pageCount` to `Pagination`, etc.; if not using `PageSizeSelect`, `pageSize` can also be passed to `Pagination` or `PrevNext`.
- Use the `sortLabels` prop on `TopSection` to pass internationalized labels for the sorting dropdowns used in the card view.
- Just like the `Table`, the `DataGrid` should be rendered as a descendant of `ScreenSizeProvider` to take advantage of the card carousel feature.
- If you would like to use the `DataGrid.Pagination` component, you must include `pageCount` OR `itemCount` & `pageSize` in `paginationOptions`. If no page count is known, you should use `DataGrid.PrevNext` instead.
- Similar to the `Table` component, the `DataGrid` exposes the `cardBreakpoint` prop, where you can define at what breakpoint you would like to switch to card
  view. It defaults to `tiny` but you can select from any of our breakpoints: `tiny`, `small`, `medium`, `large` and `extraLarge`.
- Alternatively, you can pass `variant` to directly control whether it renders as cards or a table.
- Make sure the sub-components that are rendered with the table are positioned as expected in both table view and card view. You may need to make use of `ScreenSizeContext`
  to accomplish the positioning you desire depending on the screen's size.

### Example

```
const YesNo = ({ value }) => <div>{value ? 'YES' : 'NO'}</div>

const initialPageSize = 4
const DataGridContainer = ({ data: INITIAL_DATA }) => {
  const [data, setData] = React.useState(() => INITIAL_DATA.slice(0, initialPageSize))
  const onPagisort = ({ itemOffset, pageSize: newPageSize, sort: newSortOptions }) => {
    const sortId = newSortOptions[0].id
    const sortAscending = newSortOptions[0].sortAscending
    const dataCopy = [...INITIAL_DATA]
    if (sortId === 'created') {
      if (sortAscending) {
        dataCopy.sort((a, b) => {
          return new Date(a.created) - new Date(b.created)
        })
      } else {
        dataCopy.sort((a, b) => {
          return new Date(b.created) - new Date(a.created)
        })
      }
    } else if (sortId === 'active') {
      if (sortAscending) {
        dataCopy.sort((a, b) => {
          return a.active === b.active ? 0 : a.active ? 1 : -1
        })
      } else {
        dataCopy.sort((a, b) => {
          return a.active === b.active ? 0 : a.active ? -1 : 1
        })
      }
    }
    setData(dataCopy.slice(itemOffset, itemOffset + newPageSize))
  }
  return (
    <DataGrid onPagisort={onPagisort} cardBreakpoint="tiny">
      <DataGrid.TopSection justifyContent="flex-end" spacing={4}>
        <DataGrid.PageSizeSelect
           initialPageSize={initialPageSize}
           pageSizeOptions={[4, 6, 12]}
        />
      </DataGrid.TopSection>
      <DataGrid.Table data={data}>
        <DataGrid.Column id="name" title="Name" />
        <DataGrid.Column id="created" title="Created" sortable />
        <DataGrid.Column id="active" title="Active" sortable as={YesNo} />
        <DataGrid.Column>
          {(rowData) => (
            <SplitButton onSelectMainAction={() => {}} mainActionLabel="Edit">
              <SplitButton.Action onSelect={() => {}}>Clone</SplitButton.Action>
              <SplitButton.Action onSelect={() => {}}>Delete</SplitButton.Action>
            </SplitButton>
          )}
        </DataGrid.Column>
      </DataGrid.Table>
      <DataGrid.BottomSection justifyContent="flex-end">
        <DataGrid.Pagination itemCount={INITIAL_DATA.length} />
      </DataGrid.BottomSection>
    </DataGrid>
  )
}
```

## Properties

### DataGrid
<PropsTable of={DataGrid} fileName="DataGrid/DataGrid.tsx" />

### DataGrid.TopSection
<PropsTable of={DataGrid} staticProp="DataGrid.TopSection" />

### DataGrid.Table
<PropsTable of={DataGrid.Table} />

### DataGrid.BottomSection
<PropsTable of={DataGrid} staticProp="DataGrid.BottomSection" />

### DataGrid.Pagination
<PropsTable of={DataGrid} staticProp="Pagination" />

### DataGrid.PrevNext
<PropsTable of={DataGrid} staticProp="PrevNext" />

### DataGrid.Column
<PropsTable of={DataGrid} staticProp="DataGrid.Column" />
