Migrating from AG Grid
Map AG Grid concepts, props, and column definitions onto Wit Grid.
Wit Grid and AG Grid solve the same problem — a virtualized, editable data grid — and share a lot of vocabulary
(rowData/rows, columnDefs/columns, rowModelType, masterDetail). Most of a migration is a mechanical
rename. The differences that aren't mechanical are called out explicitly below.
AG Grid API surface varies by version
AG Grid's exact prop and method names have shifted across major versions (legacy rowSelection='multiple' vs. the newer rowSelection= {{ mode: 'multiRow' }} object API, for example). This guide targets the long-stable core concepts. Check your installed AG Grid version's docs
for the exact current spelling of a prop before assuming this table is literal.
Package and root component
import { AgGridReact } from 'ag-grid-react';
<AgGridReact rowData={rows} columnDefs={columnDefs} getRowId={(p) => p.data.id} onGridReady={(p) => (apiRef.current = p.api)} />;Two shape differences that trip people up on the first pass:
getRowIdtakes the row directly, not a wrappedparams.data.onGridReadyhands you{ api, rowModelType }directly, not aparamsobject you dig.apiout of. There's no separateonFirstDataRendered—onGridReadyfires once, after the grid's first paint.
Column definitions
| AG Grid | Wit Grid | Notes |
|---|---|---|
field | field | Same. Dot paths for nested data work the same way. |
headerName | header | Renamed. |
width / minWidth / maxWidth | width / minWidth / maxWidth | Same. |
sortable | canSort | On by default: canSort: false turns it off. |
filter: true | 'agTextColumnFilter' | filterDef: { type: 'text' } (the default) | Also number, date, select (options, server-loaded, list cells), boolean, dateRange, path, custom. See Filtering. |
editable: boolean | (params) => bool | canEdit: boolean | reason | (params) => … | Editable by default; false, a reason, or a function returning true or why not. See Grid API. |
cellRenderer | cellRenderer or renderer: { kind, ... } | cellRenderer takes a component with the same shape; renderer is the lower-level spec form. |
cellEditor | cellEditor | Same idea — a component, not a class. |
valueGetter | valueGetter | Same idea; params shape differs slightly ({ row } not { data }). |
valueFormatter | format | Same idea; parse is the way back from text. |
valueSetter | valueSetter | Return false to reject a commit (same convention as AG Grid). |
pinned: 'left' | 'right' | pinned: 'left' | 'right' | Same. |
checkboxSelection | rowSelection: 'multiple' (or { mode: 'single', checkboxes: true }) | The checkbox column is the grid's own. |
rowGroup: true (per column) | initialState.grouping.by (grid-level) | Different model — see Grouping below. |
aggFunc (per column) | initialState.aggregation (grid-level) | Same built-in names (sum/avg/min/max/count/first/last), different location. |
See the full column shape in Columns.
Row grouping & aggregation
AG Grid marks grouping and aggregation on the column (rowGroup: true, aggFunc: 'sum'). Wit Grid keeps
both on the grid, in initialState — the column stays a plain column definition:
const columnDefs = [
{ field: 'department', rowGroup: true, hide: true },
{ field: 'salary', aggFunc: 'sum' },
];Group rows are cell rows with an auto group column, as in AG Grid:
| AG Grid | Wit Grid |
|---|---|
groupDisplayType: 'singleColumn' | grouping.display: 'column' (default) |
groupDisplayType: 'multipleColumns' | grouping.display: 'columns' |
groupDisplayType: 'groupRows' + groupRowRenderer | grouping.display: 'row' + groupRowRenderer |
autoGroupColumnDef | hierarchyColumn |
groupTotalRow / grandTotalRow | grouping.totals.groups / grouping.totals.grand |
groupDefaultExpanded | grouping.defaultExpanded (boolean, levels, or a predicate) |
See Grouping & Tree Data for the details and the expansion API
(the expand, collapse, expandAll and collapseAll commands, and the expansion state).
Row models
Both grids use the same three-way split, and the names are close enough to be a find-and-replace:
AG Grid rowModelType | Wit Grid rowModelType |
|---|---|
'clientSide' (default) | 'client' (default) |
'infinite' | 'infinite' |
'serverSide' | 'server' |
The datasource contract is where they diverge — AG Grid uses a success/fail callback shape, Wit Grid uses a
Promise:
const datasource = {
getRows(params) {
fetch(`/api/rows?start=${params.startRow}&end=${params.endRow}`)
.then((res) => res.json())
.then((data) => params.successCallback(data.rows, data.lastRow))
.catch(() => params.failCallback());
},
};Throw (or reject) instead of calling a failCallback; the grid marks that block failed. An AbortSignal is
provided for free — no manual request-cancellation bookkeeping. See Row Models for the
full request/response shape, including the server row model's route-aware request.
Master-detail
The mental model is the same — a nested grid under an expandable row — and the prop names are nearly identical:
| AG Grid | Wit Grid |
|---|---|
masterDetail: true | detail={{}} |
isRowMaster | detail.isMaster |
detailCellRenderer | detailRowRenderer |
detailRowHeight | detail.height |
See Master-Detail for the full renderer signature — Wit Grid's detail renderer
receives { visualRow, api }, where the nested grid is a fully independent <Grid> instance you render yourself
(not a configured sub-grid options object).
Selection
<Grid rows={rows} columns={columns} getRowId={(row) => row.id} rowSelection='multiple' />rowSelection takes the same 'single' | 'multiple' shorthand as AG Grid's mode string, or an options object
({ mode, selectAllScope }) for finer control over what "select all" means. See Selection.
Theming
AG Grid ships CSS-class themes (ag-theme-alpine) or, in newer versions, its JS Theming API (theme={themeQuartz}).
Wit Grid's theming is entirely JS/CSS-variable driven through GridApi — no separate theme object to import and
apply:
<Grid rows={rows} columns={columns} initialState={{ themeName: 'dark' }} />api.setState({ themeName: 'light' });
api.setOptions({ theme: { focusRing: '#10b981' } });Seven built-in themes ship out of the box, with runtime switching and system color-scheme detection. See Theming.
Clipboard, export, and undo/redo
await api.copySelectedRange(); // clipboard copy
await api.pasteFromClipboard(); // clipboard paste
await api.exportExcel(); // Excel export (keeps number, currency, percent and date formats)
api.exportCsv(); // CSV export
api.undo(); // history
api.redo();Not feature-gated behind a paid tier
In AG Grid, range selection, clipboard, Excel/CSV export beyond the basics, server-side row model, row grouping, and master-detail have at various points required an AG Grid Enterprise license. In Wit Grid, everything on this page ships in the single package — there's no separate paid tier that unlocks additional features. (Always double-check AG Grid's current pricing page for what's gated in the version you're on; their Community/Enterprise split has changed over time.)
Wit Grid is not open source
Unlike AG Grid Community, Wit Grid is proprietary, source-available software — see Installation for what that means before you commit to a migration.
What doesn't map 1:1
- No auto-generated group column. You render group rows yourself via
groupRowRenderer— more setup for a default look, full control over the result. - One rule per action. Editability is one of the column's rules (
canEdit,canSort,canGroup,canCopy,canPaste,canExport, …), eachtrue,false, a reason, or a function — see Columns. - Not on strict semver yet. See Migration Notes before you pin a version in a production migration.
Suggested migration order
Get one grid rendering
Swap <AgGridReact> for <Grid>, rename rowData→rows and columnDefs→columns/headerName→header,
fix up getRowId and onGridReady. See Quick Start.
Port column behavior
Editors, renderers, filters, capability callbacks. See Columns.
Port the row model
Client stays mostly as-is. Infinite/server datasources need their callback contract converted to
async/Promise. See Row Models.
Port grouping, master-detail, and theming last
These have the largest structural differences (per-column flags → grid-level initialState, CSS-class themes →
the theme option and themeName state) — tackle them once the basics are solid.
Last updated on