Skip to content

DataGrid

Open .md
Live preview

Loading example…

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 { DataGrid } from "@jcsoftdev/ui/containers";

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

<DataGrid
aria-label="Ventas de octubre"
data={ventas}
columns={ventaColumns}
selectable
loading={false}
hideToolbar={false}
height={440}
defaultPinned={{ left: ["id"] }}
/>
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.

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