Column Definition
Configure each React grid column individually with type, width, sorting, filtering, rendering, and editing options through the column definition object.
The ColumnDefinition interface defines how each column behaves and appears.
interface ColumnDefinition {
field: string;
colId?: string;
cellDataType: CellDataType;
width: number;
headerName?: string;
editable?: boolean;
sortable?: boolean;
filterable?: boolean;
hidden?: boolean;
resizable?: boolean;
minWidth?: number;
maxWidth?: number;
movable?: boolean;
rowDrag?: boolean;
/** Wrap long text onto new lines instead of truncating with an ellipsis. */
wrapText?: boolean;
cellRenderer?: string | ((params: CellRendererParams) => ReactNode);
editRenderer?: string | ((params: EditRendererParams) => ReactNode);
headerRenderer?: string | ((params: HeaderRendererParams) => ReactNode);
valueFormatter?: (value: CellValue) => string;
/** Pre-supplied raw values for the values filter mode (skips the distinct-value scan). */
distinctValues?: CellValue[];
/** Per-column override for column-level highlighting. Overrides grid-level computeColumnClasses for this column. */
computeColumnClasses?: (context: HighlightContext) => string[];
/** Per-column override for cell-level highlighting. Overrides grid-level computeCellClasses for cells in this column. */
computeCellClasses?: (context: HighlightContext) => string[];
}Required Properties
field
Type: string
The property name in the row data object.
// For data like { id: 1, firstName: "Giovanni" }
{ field: "firstName", cellDataType: "text", width: 150 }cellDataType
Type: CellDataType
The data type of the cell. Used for formatting, sorting, and filtering.
| Value | Description |
|---|---|
"text" | String values |
"number" | Numeric values |
"boolean" | Boolean values |
"date" | Date objects |
"dateString" | ISO date strings |
"dateTime" | DateTime objects |
"dateTimeString" | ISO DateTime strings |
"object" | Complex objects |
width
Type: number
Column width in pixels.
{ field: "email", cellDataType: "text", width: 250 }Optional Properties
colId
Type: string
Default: Same as field
Unique identifier for the column. Useful when multiple columns use the same field.
{
field: "price",
colId: "originalPrice",
cellDataType: "number",
width: 100
}headerName
Type: string
Default: Same as field
Display name shown in the column header.
{
field: "firstName",
headerName: "First Name",
cellDataType: "text",
width: 150
}editable
Type: boolean
Default: false
Enable inline editing for this column.
{
field: "email",
cellDataType: "text",
width: 250,
editable: true
}sortable
Type: boolean
Default: true (when sortingEnabled is true on Grid)
Enable sorting for this column.
{
field: "id",
cellDataType: "number",
width: 80,
sortable: false // Disable sorting for this column
}filterable
Type: boolean
Default: true
Enable filtering for this column.
{
field: "status",
cellDataType: "text",
width: 100,
filterable: false
}hidden
Type: boolean
Default: false
Whether the column is hidden. Hidden columns are not rendered but still exist in the definition.
{
field: "internalId",
cellDataType: "text",
width: 100,
hidden: true // Column exists but isn't visible
}resizable
Type: boolean
Default: true
Whether the column can be resized by dragging the header edge.
{
field: "id",
cellDataType: "number",
width: 80,
resizable: false // Fixed width
}minWidth
Type: number
Default: 50
Minimum width in pixels when resizing.
maxWidth
Type: number
Default: undefined (no limit)
Maximum width in pixels when resizing.
{
field: "name",
cellDataType: "text",
width: 150,
minWidth: 80,
maxWidth: 400
}movable
Type: boolean
Default: true
Whether the column can be moved/reordered by dragging its header.
{
field: "id",
cellDataType: "number",
width: 80,
movable: false // Cannot be reordered
}rowDrag
Type: boolean
Default: false
Whether this column acts as a drag handle for row dragging. When set to true, clicking and dragging cells in this column initiates a row drag.
{
field: "handle",
cellDataType: "text",
width: 40,
rowDrag: true,
sortable: false
}wrapText
Type: boolean
Default: false
Whether long cell text wraps onto new lines instead of being truncated with an ellipsis. Wrapped text is clipped to the fixed row height (rows do not auto-grow), so pair it with the native tooltip or the double-click peek overlay to read the full value. Only affects the default text renderer, not custom cellRenderer output.
{
field: "bio",
cellDataType: "text",
width: 300,
wrapText: true,
}cellRenderer
Type: string | ((params: CellRendererParams) => ReactNode)
Custom cell renderer. Pass a function directly or a string key to look up from the cellRenderers registry.
// Inline function — simplest approach
{
field: "status",
cellDataType: "text",
width: 100,
cellRenderer: (params) => (
<div className="flex items-center h-full px-2">
<span className={params.value === "Active" ? "text-green-500" : "text-red-500"}>
{params.value as string}
</span>
</div>
)
}
// String key — reference from cellRenderers registry
{ field: "status", cellDataType: "text", width: 100, cellRenderer: "status" }editRenderer
Type: string | ((params: EditRendererParams) => ReactNode)
Custom edit renderer. Pass a function directly or a string key to look up from the editRenderers registry.
headerRenderer
Type: string | ((params: HeaderRendererParams) => ReactNode)
Custom header renderer. Pass a function directly or a string key to look up from the headerRenderers registry.
valueFormatter
Type: (value: CellValue) => string
Converts a raw cell value into the string the grid treats as the cell's display value. The formatter runs before the default cell renderer paints the cell, so the output is what the user sees on screen.
Beyond display, each feature uses the formatter in a specific way:
- Values (checkbox) filter mode — the popup groups its checkbox entries by formatted label; ticking a label selects every raw value that renders as that label. The filter model itself — and any request sent to a server data source — always carries the raw values, never the labels.
- Free-text filter conditions (
contains,equals, ...) — compared against the formatted string, so users can type exactly what they see in the cell. - Copy to clipboard — copies the formatted string.
- Sorting — compares raw values; the formatter is not involved.
{
field: "salary",
cellDataType: "number",
width: 140,
headerName: "Salary",
valueFormatter: (value) => `$${(value as number).toLocaleString()}`,
}The signature takes the raw value directly ((value) => ...), not a params object. Inside a cellRenderer the params.value you receive is already the formatted string when a valueFormatter is set — read params.rowData[column.field] if the renderer needs the raw value.
Pairing with cellRenderer
A cellRenderer only changes how a cell is painted; it does not change the value used by filters or sort. If a renderer shows a string the raw value alone cannot produce (e.g. currency symbols, status icons, formatted dates), pair it with a valueFormatter so both stay in sync:
{
field: "salary",
cellDataType: "number",
width: 140,
cellRenderer: SalaryRenderer,
valueFormatter: (value) => `$${(value as number).toLocaleString()}`,
}Without the formatter, a user typing "$82,000" into a free-text condition would match nothing because the comparison would run against the raw 82000.
Formatters that collapse values
Several raw values may format to the same label (e.g. dates formatted to their month). The values filter shows one checkbox per label, and ticking it selects all raw values behind it — but only the raw values the grid has discovered. On high-cardinality columns, pre-supply the full raw domain via distinctValues so no raw value is missed:
{
field: "priority",
cellDataType: "number",
width: 120,
valueFormatter: (value) => (value as number) > 1 ? "High" : "Low",
distinctValues: [0, 1, 2, 3], // full raw domain, raw values only
}The grid warns in the console when its distinct-value scan is cut short for a formatted column.
Common use cases
Formatting "object"-type columns where the default JSON.stringify is unhelpful:
{
field: "address",
cellDataType: "object",
width: 250,
valueFormatter: (value) => {
const addr = value as { city: string; country: string };
return `${addr.city}, ${addr.country}`;
},
}Date display with a library-free format:
{
field: "createdAt",
cellDataType: "dateString",
width: 140,
valueFormatter: (value) => new Date(value as string).toLocaleDateString(),
}Null-safe formatting:
valueFormatter: (value) => value == null ? "—" : String(value),computeColumnClasses
Type: (context: HighlightContext) => string[]
Per-column override for column-level highlighting. If defined, it overrides the grid-level computeColumnClasses for this column. The context has colIndex set and rowIndex is null.
{
field: "status",
cellDataType: "text",
width: 120,
computeColumnClasses: (context) =>
context.colIndex === 0 ? ["first-column"] : [],
}computeCellClasses
Type: (context: HighlightContext) => string[]
Per-column override for cell-level highlighting. If defined, it overrides the grid-level computeCellClasses for cells in this column. The context has both rowIndex and colIndex set.
{
field: "score",
cellDataType: "number",
width: 100,
computeCellClasses: (context) => {
const value = context.rowData?.score as number;
if (value != null && value < 60) return ["bg-red-50"];
if (value != null && value >= 90) return ["bg-green-50"];
return [];
},
}For full context shape, see the Styling guide.
Example
const columns: ColumnDefinition[] = [
{
field: "id",
cellDataType: "number",
width: 80,
headerName: "ID",
sortable: true,
filterable: false,
editable: false,
},
{
field: "name",
cellDataType: "text",
width: 200,
headerName: "Full Name",
editable: true,
},
{
field: "salary",
cellDataType: "number",
width: 120,
headerName: "Salary",
editable: true,
cellRenderer: "currency",
},
{
field: "status",
cellDataType: "text",
width: 100,
headerName: "Status",
cellRenderer: "status",
editRenderer: "statusDropdown",
},
];Grid Props
Reference for every prop accepted by the React Grid component, covering data sources, columns, selection, sorting, styling, and interactivity options.
Data Sources
Connect the React grid to client-side arrays or server-side endpoints, and plug streaming, paginated, or fully remote data flows into gp-grid with ease.