# DataGrid

> Data grid with sorting, filters, quick search, column pinning, resizing, reordering and visibility, row selection, grouping with aggregates, inline editing, virtualized rows or pa…

Source: https://ui.jcsoftdev.com/docs/components/data-grid

Data grid with sorting, filters, quick search, column pinning, resizing, reordering and
visibility, row selection, grouping with aggregates, inline editing, virtualized rows or
pagination, CSV export, and full keyboard navigation (ARIA grid pattern, roving tabindex).
It adapts to its container width: the toolbar wraps and the grid scrolls horizontally with
its pinned columns kept in place.

## Import

```ts
import { DataGrid } from "@jcsoftdev/ui/containers";
```

Single-component entry points tree-shake to just this component: `@jcsoftdev/ui/containers/data-grid`.

## Usage

```tsx
<DataGrid
  aria-label="Ventas de octubre"
  data={ventas}
  columns={ventaColumns}
  selectable
  loading={false}
  hideToolbar={false}
  height={440}
  defaultPinned={{ left: ["id"] }}
/>
```

## Props

| Prop | Type | Default | Description |
| --- | --- | --- | --- |
| `data` | `readonly T[]` | `EMPTY_DATA as readonly T[]` | Rows to show. Optional with `dataSource`, which loads them. |
| `columns` * | `readonly DataGridColumn<T>[]` |  |  |
| `aria-label` * | `string` |  | Accessible name of the grid. |
| `getRowId` | `((row: T, index: number) => string)` |  | Stable row id (selection, editing, keys). The data index by default. |
| `height` | `number` | `480` | Maximum height of the scrolling body in px (virtualized mode). |
| `pageSize` | `number` |  | Switches from virtualized scrolling to pagination with this page size. |
| `pageSizeOptions` | `readonly number[]` | `[25, 50, 100]` |  |
| `storageKey` | `string` |  | localStorage key that remembers column order, widths, visibility, pins and density. |
| `sort` | `readonly SortRule[]` |  |  |
| `defaultSort` | `readonly SortRule[]` | `EMPTY_SORT` |  |
| `onSortChange` | `((sort: SortRule[]) => void)` |  |  |
| `filters` | `Readonly<Record<string, FilterValue>>` |  |  |
| `defaultFilters` | `Readonly<Record<string, FilterValue>>` | `EMPTY_FILTERS` |  |
| `onFiltersChange` | `((filters: Filters) => void)` |  |  |
| `groupBy` | `readonly string[]` |  |  |
| `defaultGroupBy` | `readonly string[]` | `EMPTY_LIST` |  |
| `onGroupByChange` | `((groupBy: string[]) => void)` |  |  |
| `defaultPinned` | `{ left?: readonly string[]; right?: readonly string[]; }` |  |  |
| `defaultHidden` | `readonly string[]` |  |  |
| `density` | `"normal" \| "compact" \| "comfortable"` |  |  |
| `defaultDensity` | `"normal" \| "compact" \| "comfortable"` | `"normal"` |  |
| `onDensityChange` | `((density: Density) => void)` |  |  |
| `selectable` | `boolean` | `false` | Adds a checkbox column; Shift selects a range. |
| `selectedRowIds` | `readonly string[]` |  |  |
| `defaultSelectedRowIds` | `readonly string[]` | `EMPTY_LIST` |  |
| `onSelectionChange` | `((ids: string[]) => void)` |  |  |
| `onCellChange` | `((change: CellChange<T>) => void)` |  | Called when an inline edit is committed with a different value. The grid does not mutate `data`. |
| `onCellsChange` | `((changes: CellChange<T>[]) => void)` |  | Called once with every cell a paste, fill, undo or redo changes. Without it those changes go to `onCellChange` one by one, which loses updates if the parent sets state from stale data. |
| `history` | `boolean` | `false` | Undo / redo of cell edits, paste, fill and row changes: buttons plus Ctrl / Cmd + Z, Shift + Ctrl / Cmd + Z, Ctrl + Y. |
| `historyDepth` | `number` | `DEFAULT_HISTORY_DEPTH` | Commands kept for undo (and for redo). 100 by default. |
| `onHistoryChange` | `((history: HistorySummary) => void)` |  |  |
| `formulas` | `boolean` | `false` | Spreadsheet formulas: a cell whose text starts with `=` is evaluated (`=B2*C2`, `=SUM(D2:D9)`, `=IF(E2>100,"alto","bajo")`). Columns are lettered in the order of `columns` and rows are numbered in the order of `data`; a formula bar shows the raw content of th… |
| `createRow` | `(() => T)` |  | Adds the "add row" button: the new row is appended through `onRowsChange`. |
| `onRowsChange` | `((change: RowsChange<T>) => void)` |  | Rows added (`createRow`), removed (the toolbar button removes the selected rows) or restored by undo. |
| `dataSource` | `DataSource<T>` |  | Server-side rows. Sort, filters and quick search are sent to `getRows` instead of being applied here; with `pageSize` the grid pages through blocks of that size, without it rows are loaded as you scroll. Grouping, tree data, row pinning, pivot and detail rows… |
| `maxBlocks` | `number` |  | Blocks kept in memory in infinite mode before the least recently used are dropped. |
| `tree` | `{ getParentId: (row: T) => string \| null \| undefined; }` |  | Shows `data` as a tree: `getParentId` links a row to its parent (nullish for roots). |
| `expandedRowIds` | `readonly string[]` |  | Expanded row ids: tree nodes and rows with a detail panel. |
| `defaultExpandedRowIds` | `readonly string[]` | `EMPTY_LIST` |  |
| `onExpandedRowsChange` | `((ids: string[]) => void)` |  |  |
| `renderDetail` | `((row: T, rowId: string) => ReactNode)` |  | Detail panel (master / detail) rendered under an expanded row. |
| `detailHeight` | `number \| ((row: T) => number)` | `DEFAULT_DETAIL_HEIGHT` | Height of a detail panel in px (fixed so rows stay virtualizable). 240 by default. |
| `rowPinning` | `boolean` | `false` | Adds pin-to-top / pin-to-bottom buttons to rows; pinned rows stay in view while scrolling. |
| `pinnedRows` | `PinnedRows` |  |  |
| `defaultPinnedRows` | `PinnedRows` | `NO_PINNED_ROWS` |  |
| `onPinnedRowsChange` | `((pinned: PinnedRows) => void)` |  |  |
| `rowReorder` | `boolean` | `false` | Drag handle and Alt + arrows to reorder rows; works without sort, filters or grouping. |
| `onRowReorder` | `((event: RowReorderEvent) => void)` |  | Called with the new order; the grid does not mutate `data`. |
| `rangeSelection` | `boolean` | `false` | Rectangular cell selection by drag, Shift + click or Shift + arrows, with Ctrl + C as TSV. |
| `fillSeries` | `{ dateStep?: DateStepMode; }` |  | How the fill handle reads series. `dateStep`: "auto" (default) continues dates by months when they share the day of the month and by days otherwise; "day" and "month" force one unit. |
| `charts` | `boolean` | `false` | Adds a "Graficar" button to the range status bar (turns `rangeSelection` on): the selected cells open a bar, line, area or pie chart under the grid. The text column of the range names the categories and each numeric column is a series. The chart code is loade… |
| `advancedFilter` | `FilterGroup` |  | Advanced filter (AND / OR groups of conditions) applied after the column filters. |
| `defaultAdvancedFilter` | `FilterGroup` | `EMPTY_ADVANCED` |  |
| `onAdvancedFilterChange` | `((filter: FilterGroup) => void)` |  |  |
| `showAdvancedFilter` | `boolean` | `false` | Adds the advanced filter button to the toolbar. |
| `toolPanel` | `boolean` | `false` | Side panel to show, hide and reorder columns, group rows and set up a pivot. |
| `defaultToolPanelOpen` | `boolean` | `false` |  |
| `pivot` | `PivotConfig` |  | Pivot: row fields x pivot column x aggregated value. |
| `defaultPivot` | `PivotConfig` | `EMPTY_PIVOT` |  |
| `onPivotChange` | `((pivot: PivotConfig) => void)` |  |  |
| `loading` | `boolean` | `false` |  |
| `emptyMessage` | `ReactNode` |  | Shown when there are no rows (a filtered-out message is used when filters are active). |
| `showFooter` | `boolean` |  | Footer with the column aggregates. On when some column has `aggregate`. |
| `hideToolbar` | `boolean` | `false` | Hides search, chips, density, columns and export. |
| `exportFilename` | `string \| false` | `"datos.csv"` | CSV file name for the export button; `false` hides the button. |
| `onExport` | `((payload: ExportPayload) => void)` |  | Called with the CSV right before it is downloaded. |
| `exportXlsx` | `string \| boolean` | `false` | Adds an "Exportar XLSX" button: a file name (`"ventas.xlsx"`) or `true` for `datos.xlsx`. Same rows and columns as the CSV export, with numbers as numbers and dates as dates. The writer (`@jcsoftdev/ui/xlsx`) is loaded when the button is used, so it costs not… |
| `onExportXlsx` | `((payload: XlsxExportPayload) => void)` |  | Called with the file right before it is downloaded. |
| `toolbarActions` | `ReactNode` |  |  |
| `labels` | `Partial<DataGridLabels>` |  |  |
| `className` | `string` |  |  |

`*` marks a required prop.

## Storybook stories

- [Default](/storybook/?path=/story/containers-datagrid--default)
- [Sorting / Filtering](/storybook/?path=/story/containers-datagrid--sorting-filtering)
- [Pinning](/storybook/?path=/story/containers-datagrid--pinning)
- [Grouping](/storybook/?path=/story/containers-datagrid--grouping)
- [Editing](/storybook/?path=/story/containers-datagrid--editing)
- [Virtualized 10k](/storybook/?path=/story/containers-datagrid--virtualized-10-k)
- [Pagination](/storybook/?path=/story/containers-datagrid--pagination)
- [Narrow (320 px)](/storybook/?path=/story/containers-datagrid--narrow)
- [Dark](/storybook/?path=/story/containers-datagrid--dark)
- [Loading](/storybook/?path=/story/containers-datagrid--loading)
- [Empty](/storybook/?path=/story/containers-datagrid--empty)
- [Column types](/storybook/?path=/story/containers-datagrid--column-types)
- [Validation](/storybook/?path=/story/containers-datagrid--validation)
- [Reorder / resize / hide](/storybook/?path=/story/containers-datagrid--reorder-resize-hide)
- [Column groups](/storybook/?path=/story/containers-datagrid--column-groups)
- [Column groups (320 px)](/storybook/?path=/story/containers-datagrid--column-groups-narrow)
- [Row pinning](/storybook/?path=/story/containers-datagrid--row-pinning)
- [Row reorder](/storybook/?path=/story/containers-datagrid--row-reorder)
- [Row expansion](/storybook/?path=/story/containers-datagrid--row-expansion)
- [State persistence](/storybook/?path=/story/containers-datagrid--state-persistence)
- [Keyboard navigation](/storybook/?path=/story/containers-datagrid--keyboard-navigation)
- [Tree data](/storybook/?path=/story/containers-datagrid--tree-data)
- [Remote pagination](/storybook/?path=/story/containers-datagrid--remote-pagination)
- [Infinite scroll](/storybook/?path=/story/containers-datagrid--infinite-scroll)
- [Set filter](/storybook/?path=/story/containers-datagrid--set-filter)
- [Filter builder](/storybook/?path=/story/containers-datagrid--filter-builder)
- [Filter builder (toolbar)](/storybook/?path=/story/containers-datagrid--filter-builder-toolbar)
- [Filter builder (320 px)](/storybook/?path=/story/containers-datagrid--filter-builder-narrow)
- [Range selection](/storybook/?path=/story/containers-datagrid--range-selection)
- [Range selection (320 px)](/storybook/?path=/story/containers-datagrid--range-selection-narrow)
- [Pivot](/storybook/?path=/story/containers-datagrid--pivot)
- [Master / detail](/storybook/?path=/story/containers-datagrid--master-detail)
- [Tool panel](/storybook/?path=/story/containers-datagrid--tool-panel)
- [Tool panel (320 px)](/storybook/?path=/story/containers-datagrid--tool-panel-narrow)
- [Export CSV](/storybook/?path=/story/containers-datagrid--export-csv)
- [Default](/storybook/?path=/story/containers-datagrid-filterbuilder--default)
- [Empty](/storybook/?path=/story/containers-datagrid-filterbuilder--empty)
- [Narrow](/storybook/?path=/story/containers-datagrid-filterbuilder--narrow)
- [Undo / redo](/storybook/?path=/story/containers-datagrid-spreadsheet--undo-redo)
- [Undo / redo (320 px)](/storybook/?path=/story/containers-datagrid-spreadsheet--undo-redo-narrow)
- [Undo / redo (bordered preset)](/storybook/?path=/story/containers-datagrid-spreadsheet--undo-redo-preset)
- [Formulas](/storybook/?path=/story/containers-datagrid-spreadsheet--formulas)
- [Formulas (320 px)](/storybook/?path=/story/containers-datagrid-spreadsheet--formulas-narrow)
- [Formulas (elevated preset)](/storybook/?path=/story/containers-datagrid-spreadsheet--formulas-preset)
- [Formula errors](/storybook/?path=/story/containers-datagrid-spreadsheet--formula-errors)
- [Export XLSX](/storybook/?path=/story/containers-datagrid-spreadsheet--export-xlsx)
- [Export XLSX (320 px)](/storybook/?path=/story/containers-datagrid-spreadsheet--export-xlsx-narrow)
- [Export XLSX (glass preset)](/storybook/?path=/story/containers-datagrid-spreadsheet--export-xlsx-preset)
- [Integrated charts](/storybook/?path=/story/containers-datagrid-spreadsheet--integrated-charts)
- [Integrated charts (320 px)](/storybook/?path=/story/containers-datagrid-spreadsheet--integrated-charts-narrow)
- [Integrated charts (flat preset)](/storybook/?path=/story/containers-datagrid-spreadsheet--integrated-charts-preset)
- [Sparkline column](/storybook/?path=/story/containers-datagrid-spreadsheet--sparkline-column)
- [Sparkline column (320 px)](/storybook/?path=/story/containers-datagrid-spreadsheet--sparkline-column-narrow)
- [Fill handle](/storybook/?path=/story/containers-datagrid-spreadsheet--fill-handle)
- [Fill handle (320 px)](/storybook/?path=/story/containers-datagrid-spreadsheet--fill-handle-narrow)
- [Fill handle (bordered preset)](/storybook/?path=/story/containers-datagrid-spreadsheet--fill-handle-preset)
- [Fill handle (up, left and auto-scroll)](/storybook/?path=/story/containers-datagrid-spreadsheet--fill-up-and-left)
- [Fill handle (up, left, 320 px)](/storybook/?path=/story/containers-datagrid-spreadsheet--fill-up-and-left-narrow)

## Source

`packages/ui/src/containers/data-grid/data-grid.tsx`
