Skip to content

DataGridProps

Props for the DataGrid component.

PropertyTypeDescription
rowsTRow[]Row data to display
gridConfig?GridConfig<TRow>Grid configuration. Supports React renderers/editors via reactRenderer and reactEditor properties.
columns?ColumnShorthand<TRow>[]Column definitions. Supports shorthand syntax for quick definitions.
columnDefaults?Partial<ColumnConfig<TRow>>Default column properties applied to all columns. Individual column definitions override these defaults.
fitMode?stretch | fit-columns | auto-fitFit mode for column sizing
sortable?booleanGrid-wide sorting toggle. When false, disables sorting for all columns regardless of their individual sortable setting. When true (default), columns with sortable: true can be sorted.
filterable?booleanGrid-wide filtering toggle. When false, disables filtering for all columns regardless of their individual filterable setting. When true (default), columns with filterable: true can be filtered.
selectable?booleanGrid-wide selection toggle. When false, disables selection for all rows/cells. When true (default), selection is enabled based on plugin mode.
loading?booleanShow a loading overlay on the grid. Use this during initial data fetch or refresh operations.
customStyles?stringCustom CSS styles to inject into the grid via document.adoptedStyleSheets
className?stringClass name for the grid element
style?CSSPropertiesInline styles for the grid element
children?ReactNodeChildren (GridColumn components for custom renderers/editors)
plugins?BaseGridPlugin<unknown>[]Escape hatch: manually provide plugin instances. When provided, feature props for those plugins are ignored. Useful for advanced configurations not covered by feature props.
onRowsChange?(rows: TRow[]) => voidFired when rows change (sorting, editing, etc.)
onCellClick?EventHandler<CellClickDetail<TRow>>Fired when a cell is clicked.
onRowClick?EventHandler<RowClickDetail<TRow>>Fired when a row is clicked.
onCellActivate?EventHandler<CellActivateDetail<TRow>>Fired when a cell is activated (Enter key or double-click).
onCellChange?EventHandler<CellChangeDetail<TRow>>Fired when a cell value changes (before commit).
onCellCommit?EventHandler<CellCommitDetail<TRow>>Fired when a cell edit is committed. Cancelable - call event.preventDefault() to reject the edit.
onRowCommit?EventHandler<RowCommitDetail<TRow>>Fired when all pending row edits are committed.
onChangedRowsReset?EventHandler<ChangedRowsResetDetail<TRow>>Fired when changed rows cache is reset via resetChangedRows().
onEditOpen?EventHandler<EditOpenDetail<TRow>>Fired when an editor opens for a cell.
onBeforeEditClose?EventHandler<BeforeEditCloseDetail<TRow>>Fired before an editor closes (commit or cancel). Cancelable.
onEditClose?EventHandler<EditCloseDetail<TRow>>Fired after an editor closes (commit or cancel).
onCellCancel?EventHandler<CellCancelDetail>Fired when a cell edit is canceled (e.g. Escape key).
onDirtyChange?EventHandler<DirtyChangeDetail<TRow>>Fired when the dirty/changed-rows state transitions.
onDataChange?EventHandler<DataChangeDetail>Fired when the row data is replaced (e.g. via the data property setter).
onSortChange?EventHandler<SortChangeDetail>Fired when sort state changes.
onFilterChange?EventHandler<FilterChangeDetail>Fired when filter values change.
onColumnResize?EventHandler<ColumnResizeDetail>Fired when a column is resized.
onColumnMove?EventHandler<ColumnMoveDetail>Fired when a column is moved via drag-and-drop. Cancelable - call event.preventDefault() to cancel the move.
onColumnResizeReset?EventHandler<ColumnResizeResetDetail>Fired when a column resize is reset (e.g. via double-click on the resize handle).
onColumnVisibility?EventHandler<ColumnVisibilityDetail>Fired when a column is shown or hidden — either via the visibility sidebar, grid.toggleColumnVisibility(field), grid.setColumnVisible(field, visible), or grid.showAllColumns().
onColumnStateChange?EventHandler<GridColumnState>Fired when column state changes (resize, reorder, visibility). Useful for persisting column state.
onSelectionChange?EventHandler<SelectionChangeDetail>Fired when selection changes.
onRowMove?EventHandler<RowMoveDetail<TRow>>Fired when a row is moved via drag-and-drop. Cancelable - call event.preventDefault() to cancel the move.
onRowDragStart?EventHandler<RowDragStartDetail<TRow>>Fired when a row drag starts. Cancelable.
onRowDragEnd?EventHandler<RowDragEndDetail<TRow>>Fired when a row drag ends (after drop or cancel).
onRowDrop?EventHandler<RowDropDetail<TRow>>Fired on the target grid when rows are dropped from another grid. Cancelable.
onRowTransfer?EventHandler<RowTransferDetail<TRow>>Fired on BOTH source and target grids after a successful cross-grid row transfer.
onGroupToggle?EventHandler<GroupToggleDetail>Fired when a group is expanded or collapsed.
onGroupExpand?EventHandler<GroupExpandDetail>Fired when a group is expanded.
onGroupCollapse?EventHandler<GroupCollapseDetail>Fired when a group is collapsed.
onContextMenuOpen?EventHandler<ContextMenuOpenDetail>Fired when the context menu opens.
onTreeExpand?EventHandler<TreeExpandDetail<TRow>>Fired when a tree node is expanded.
onDetailExpand?EventHandler<DetailExpandDetail>Fired when a detail panel is expanded or collapsed.
onResponsiveChange?EventHandler<ResponsiveChangeDetail>Fired when responsive mode changes (table ↔ card).
onCopy?EventHandler<CopyDetail>Fired when cells are copied to clipboard.
onPaste?EventHandler<PasteDetail>Fired when cells are pasted from clipboard.
onUndo?EventHandler<UndoRedoDetail>Fired when an undo action is performed.
onRedo?EventHandler<UndoRedoDetail>Fired when a redo action is performed.
onExportComplete?EventHandler<ExportCompleteDetail>Fired when export completes.
onPrintStart?EventHandler<PrintStartDetail>Fired when print starts.
onPrintComplete?EventHandler<PrintCompleteDetail>Fired when print completes.
onTbwScroll?EventHandler<TbwScrollDetail>Fired (rAF-batched) when the grid’s viewport scrolls vertically.
onRender?EventHandler<RenderDetail>Fired once at the end of every render-scheduler flush, after all plugin afterRender hooks have run and ready() has resolved.
selection?cell | row | range | SelectionConfig<TRow>Enable cell/row/range selection.
editing?boolean | click | dblclick | manual | EditingConfigEnable inline cell editing.
clipboard?boolean | ClipboardConfigEnable clipboard copy/paste. Requires selection to be enabled (will be auto-added).
contextMenu?boolean | ContextMenuConfigEnable right-click context menu.
multiSort?boolean | multi | MultiSortConfig | singleEnable multi-column sorting.
filtering?boolean | FilterConfig<TRow>Enable column filtering.
reorderColumns?boolean | ReorderConfigEnable column drag-to-reorder.
visibility?boolean | VisibilityConfigEnable column visibility toggle panel.
pinnedColumns?booleanEnable pinned/sticky columns. Columns are pinned via the sticky column property.
groupingColumns?boolean | GroupingColumnsConfigEnable multi-level column headers (column groups).
columnVirtualization?boolean | ColumnVirtualizationConfigEnable horizontal column virtualization for wide grids.
reorderRows?boolean | RowReorderConfig⚠️ Enable row drag-to-reorder.
rowDragDrop?boolean | RowDragDropConfig<TRow>Enable row drag-and-drop, both within a single grid (reorder) and across grids that share a dropZone.
groupingRows?GroupingRowsConfigEnable row grouping by field values.
pinnedRows?boolean | PinnedRowsConfigEnable pinned rows (aggregation/status bar).
stickyRows?StickyRowsConfigPin selected data rows below the header as the user scrolls past them.
tree?boolean | TreeConfigEnable hierarchical tree view.
masterDetail?MasterDetailConfigEnable master-detail expandable rows.
responsive?boolean | ResponsivePluginConfig<TRow>Enable responsive card layout for narrow viewports.
undoRedo?boolean | UndoRedoConfigEnable undo/redo for cell edits. Requires editing to be enabled (will be auto-added).
export?boolean | ExportConfigEnable CSV/JSON export functionality.
print?boolean | PrintConfigEnable print functionality.
pivot?PivotConfigEnable pivot table functionality.
serverSide?ServerSideConfigEnable server-side data operations.
tooltip?boolean | TooltipConfigEnable styled popover tooltips on overflowing cells and headers.
shell?boolean | ShellConfigEnable the grid shell (header bar + collapsible tool panels).
ssr?boolean⚠️ Enable SSR mode - skips React-side plugin instantiation.
gridConfig={{
columns: [
{
field: 'status',
reactRenderer: (ctx) => <StatusBadge value={ctx.value} />,
reactEditor: (ctx) => <StatusEditor value={ctx.value} onCommit={ctx.commit} />,
},
],
}}

// Shorthand strings (auto-generate headers from field names)
columns={['id:number', 'name', 'email', 'salary:currency']}
// Mixed: shorthand + full config
columns={['id:number', 'name', { field: 'status', editable: true }]}
// Full config objects (standard usage)
columns={[{ field: 'id', type: 'number' }, { field: 'name' }]}

<DataGrid
columnDefaults={{ sortable: true, resizable: true }}
columns={[
{ field: 'id', sortable: false }, // Override: not sortable
{ field: 'name' }, // Inherits: sortable, resizable
]}
/>

Grid-wide sorting toggle. When false, disables sorting for all columns regardless of their individual sortable setting. When true (default), columns with sortable: true can be sorted.

For multi-column sorting, also add the multiSort prop.

Default: true

// Disable all sorting
<DataGrid sortable={false} />
// Enable sorting with multi-sort
<DataGrid sortable multiSort />

Grid-wide filtering toggle. When false, disables filtering for all columns regardless of their individual filterable setting. When true (default), columns with filterable: true can be filtered.

Requires the FilteringPlugin to be loaded (via filtering prop or feature import).

Default: true

// Disable all filtering
<DataGrid filterable={false} filtering />
// Enable filtering (default)
<DataGrid filterable filtering />

Grid-wide selection toggle. When false, disables selection for all rows/cells. When true (default), selection is enabled based on plugin mode.

Requires the SelectionPlugin to be loaded (via selection prop or feature import).

Default: true

// Disable all selection
<DataGrid selectable={false} selection="range" />
// Enable selection (default)
<DataGrid selectable selection="range" />

Show a loading overlay on the grid. Use this during initial data fetch or refresh operations.

For row/cell loading states, use the ref to access methods:

  • ref.element.setRowLoading(rowId, true/false)
  • ref.element.setCellLoading(rowId, field, true/false)

Default: false

const [loading, setLoading] = useState(true);
useEffect(() => {
fetchData().then(data => {
setRows(data);
setLoading(false);
});
}, []);
<DataGrid loading={loading} rows={rows} />

import { SelectionPlugin } from '@toolbox-web/grid/plugins/selection';
<DataGrid
plugins={[new SelectionPlugin({ mode: 'range', checkbox: true })]}
/>

onCellClick={(detail) => console.log('Clicked:', detail.field, detail.value)}

onRowClick={(detail) => navigateTo(`/employees/${detail.row.id}`)}

onCellActivate={(detail) => openEditor(detail.field, detail.row)}

onCellChange={(detail) => validateChange(detail)}

onCellCommit={(detail, event) => {
if (!isValid(detail.value)) {
event?.preventDefault();
showError('Invalid value');
}
}}

onRowCommit={(detail) => saveToServer(detail.row)}

onChangedRowsReset={(detail) => console.log('Reset:', detail.rows.length, 'rows cleared')}

onSortChange={(detail) => console.log('Sort:', detail.field, detail.direction)}

onFilterChange={(detail) => console.log('Filters:', detail.activeFilters)}

onColumnResize={(detail) => console.log('Resized:', detail.field, detail.width)}

onColumnMove={(detail, event) => {
if (detail.column.field === 'id') {
event?.preventDefault(); // Don't allow moving ID column
}
}}

onColumnResizeReset={(detail) => console.log('Reset width for:', detail.field)}

Fired when a column is shown or hidden — either via the visibility sidebar, grid.toggleColumnVisibility(field), grid.setColumnVisible(field, visible), or grid.showAllColumns().

field and visible are present for single-column toggles and undefined for bulk operations (showAllColumns). visibleColumns always lists the current set.

onColumnVisibility={(detail) => {
console.log(detail.hidden ? 'Hidden:' : 'Shown:', detail.field);
localStorage.setItem('visibleColumns', JSON.stringify(detail.visibleColumns));
}}

onColumnStateChange={(state) => saveToLocalStorage('gridState', state)}

onSelectionChange={(detail) => {
console.log('Selected ranges:', detail.ranges);
console.log('Mode:', detail.mode);
}}

onRowMove={(detail, event) => {
if (!canMove(detail.row)) {
event?.preventDefault();
}
}}

onGroupToggle={(detail) => {
console.log(detail.expanded ? 'Expanded' : 'Collapsed', detail.key);
}}

onTreeExpand={(detail) => console.log('Expanded:', detail.row)}

onDetailExpand={(detail) => {
if (detail.expanded) loadDetailData(detail.rowId);
}}

onResponsiveChange={(detail) => {
console.log('Mode:', detail.mode); // 'table' | 'card'
}}

onCopy={(detail) => console.log('Copied:', detail.text)}

onPaste={(detail) => console.log('Pasted:', detail.affectedCells.length, 'cells')}

onUndo={(detail) => console.log('Undid:', detail.action.type, '- Can undo:', detail.canUndo)}

onRedo={(detail) => console.log('Redid:', detail.action.type, '- Can redo:', detail.canRedo)}

onExportComplete={(detail) => console.log('Exported:', detail.filename)}

onPrintStart={(detail) => console.log('Printing:', detail.rowCount, 'rows')}

onPrintComplete={() => console.log('Print complete')}

Fired (rAF-batched) when the grid’s viewport scrolls vertically.

For server-side pagination of large datasets prefer ServerSidePlugin — this event is the lower-level primitive for custom load-more triggers, deferring heavy cell content, dismissing overlays, etc.

onTbwScroll={(detail) => {
if (detail.scrollTop + detail.clientHeight >= detail.scrollHeight - 200) {
loadMore();
}
}}

Fired once at the end of every render-scheduler flush, after all plugin afterRender hooks have run and ready() has resolved.

Use this to act on the rendered DOM after a programmatic mutation (e.g. focus the first input of a freshly added row in full-grid edit mode) without setTimeout or double-requestAnimationFrame hacks. Fires on every flush — including scroll-driven virtual-window updates — so prefer subscribing once and unsubscribing (or gating on detail.phase >= RenderPhase.ROWS) when you only care about a specific mutation.

onRender={(detail) => {
if (detail.initial) console.log('first render complete');
}}

// Shorthand - just the mode
<DataGrid selection="range" />
// Full config
<DataGrid selection={{ mode: 'range', checkbox: true }} />

// Enable with default trigger (dblclick)
<DataGrid editing />
// Specify trigger
<DataGrid editing="click" />
<DataGrid editing="dblclick" />
<DataGrid editing="manual" />
// Full config with callbacks
<DataGrid editing={{ editOn: 'dblclick', onBeforeEditClose: myCallback }} />

<DataGrid selection="range" clipboard />

<DataGrid contextMenu />
<DataGrid contextMenu={{ items: customItems }} />

Enable multi-column sorting.

Multi-sort allows users to sort by multiple columns simultaneously. For basic single-column sorting, columns with sortable: true work without this plugin. Use the sortable prop to disable all sorting grid-wide.

// Enable multi-column sorting
<DataGrid multiSort />
// Limit to single column (uses plugin but restricts to 1)
<DataGrid multiSort="single" />
// Full config
<DataGrid multiSort={{ maxSortColumns: 3 }} />

<DataGrid filtering />
<DataGrid filtering={{ debounceMs: 200 }} />

<DataGrid reorderColumns />

<DataGrid visibility />

<DataGrid pinnedColumns columns={[
{ field: 'id', pinned: 'left' },
{ field: 'name' },
{ field: 'actions', pinned: 'right' },
]} />

<DataGrid groupingColumns={{
columnGroups: [
{ header: 'Personal Info', children: ['firstName', 'lastName'] },
],
}} />

<DataGrid columnVirtualization />

<DataGrid reorderRows />

// Intra-grid reorder (parity with reorderRows)
<DataGrid rowDragDrop />
// Cross-grid transfer
<DataGrid rowDragDrop={{ dropZone: 'employees', operation: 'move' }} />

<DataGrid groupingRows={{
groupOn: (row) => [row.department, row.team],
defaultExpanded: true,
}} />
To keep mouse-toggle behavior, either add the `group-toggle` class to a
clickable element (the plugin delegates clicks via `closest('.group-toggle')`)
or call `params.toggleExpand()` from your own handler.
```tsx
<DataGrid groupingRows={{
groupOn: (row) => row.department,
groupRowRenderer: (params) => (
<button type="button" className="group-toggle">
{params.expanded ? '' : ''} {params.value} ({params.rows.length})
</button>
),
}} />
---
#### pinnedRows
```tsx
<DataGrid pinnedRows={{
bottom: [{ type: 'aggregation', aggregator: 'sum' }],
}} />
<DataGrid pinnedRows={{
slots: [
{ id: 'add-row', position: 'bottom', render: () => <AddRowPanel /> },
],
}} />

// Field-name shorthand
<DataGrid stickyRows={{ isSticky: 'isSection' }} />
// Predicate + stack mode
<DataGrid stickyRows={{
isSticky: (row) => row.kind === 'section',
mode: 'stack',
maxStacked: 3,
}} />

<DataGrid tree={{
childrenField: 'children',
defaultExpanded: true,
}} />

<DataGrid masterDetail={{
renderer: (row) => <OrderDetails order={row} />,
}} />

<DataGrid responsive={{
breakpoint: 768,
cardRenderer: (row) => <EmployeeCard employee={row} />,
}} />

<DataGrid editing="dblclick" undoRedo />

<DataGrid export />
<DataGrid export={{ filename: 'data.csv' }} />

<DataGrid print />

<DataGrid pivot={{
rowFields: ['category'],
columnFields: ['year'],
valueField: 'sales',
}} />

<DataGrid serverSide={{
dataSource: async (params) => fetchData(params),
}} />

<DataGrid tooltip />
<DataGrid tooltip={{ cell: false }} />

Default: false


AI assistants: For complete API documentation, implementation guides, and code examples for this library, see https://raw.githubusercontent.com/OysteinAmundsen/toolbox/main/llms-full.txt