Key information for working with columns.
Columns define the structure of your grid. Each column describes how to access, display, and interact with data. The ActiveGrid uses a flexible column system based on TanStack Table.
const columns: GridColumnDef<User>[] = [
{
accessorKey: 'name',
header: 'Name',
},
{
accessorKey: 'email',
header: 'Email',
},
];Access data via a property key:
{
accessorKey: 'name',
header: 'Name',
}Access data via a function:
{
accessorFn: (row) => `${row.firstName} ${row.lastName}`,
header: 'Full Name',
}Display-only columns (no data accessor):
{
id: 'actions',
header: 'Actions',
cell: ({ row }) => (
<Button onClick={() => handleEdit(row.original)}>
Edit
</Button>
),
}Group related columns together:
{
id: 'personal',
header: 'Personal Information',
columns: [
{ accessorKey: 'firstName', header: 'First Name' },
{ accessorKey: 'lastName', header: 'Last Name' },
{ accessorKey: 'age', header: 'Age' },
],
}string{
accessorKey: 'name',
header: 'Name',
}
// Nested access
{
accessorKey: 'user.profile.name',
header: 'Name',
}(row: TData) => any{
accessorFn: (row) => row.firstName + ' ' + row.lastName,
header: 'Full Name',
}string{
id: 'actions',
header: 'Actions',
cell: ({ row }) => <Actions row={row} />,
}string | (props: HeaderContext) => ReactNode// String header
{
header: 'Name',
}
// Component header
{
header: ({ column }) => (
<div className="flex items-center">
<span>Name</span>
<SortIndicator column={column} />
</div>
),
}(props: CellContext) => ReactNodestring | (props: HeaderContext) => ReactNodenumbernumber60numberNumber.MAX_SAFE_INTEGERbooleantruebooleantruebooleantruebooleantrueUse meta for extended configuration:
See Column Meta for full details.
Group related columns:
Generate columns dynamically:
Include columns based on conditions:
Control which columns are visible:
Control column order:
Pin columns left or right:
Memoize columns to prevent unnecessary re-renders:
{
accessorKey: 'status',
header: 'Status',
cell: ({ getValue }) => (
<BadgeCell value={getValue()} />
),
}{
accessorKey: 'amount',
header: 'Amount',
footer: ({ table }) => {
const total = table.getFilteredRowModel().rows
.reduce((sum, row) => sum + row.getValue('amount'), 0);
return `Total: $${total.toFixed(2)}`;
},
}{
accessorKey: 'id',
header: 'ID',
size: 80,
}{
accessorKey: 'name',
header: 'Name',
minSize: 100,
}{
accessorKey: 'description',
header: 'Description',
maxSize: 400,
}{
accessorKey: 'actions',
header: 'Actions',
enableSorting: false,
}{
accessorKey: 'status',
header: 'Status',
enableResizing: false,
}{
accessorKey: 'name',
header: 'Name',
enablePinning: true,
}{
accessorKey: 'id',
header: 'ID',
enableHiding: false, // Always visible
}{
accessorKey: 'price',
header: 'Price',
meta: {
cellAlign: 'right',
valueFormatter: (value) => `$${value.toFixed(2)}`,
filterType: 'number',
editable: true,
editType: 'number',
},
}import { getSelectionColumn } from '@workspace/active-grid';
const columns = [
getSelectionColumn<User>(),
...dataColumns,
];import { getRowNumberColumn } from '@workspace/active-grid';
const columns = [
getRowNumberColumn<User>({
header: '#',
size: 50,
}),
...dataColumns,
];import { getExpanderColumn } from '@workspace/active-grid';
const columns = [
getExpanderColumn<Order>(),
...dataColumns,
];const columns: GridColumnDef<User>[] = [
{
id: 'personal',
header: 'Personal Information',
columns: [
{
accessorKey: 'firstName',
header: 'First Name',
},
{
accessorKey: 'lastName',
header: 'Last Name',
},
{
accessorKey: 'age',
header: 'Age',
},
],
},
{
id: 'contact',
header: 'Contact',
columns: [
{
accessorKey: 'email',
header: 'Email',
},
{
accessorKey: 'phone',
header: 'Phone',
},
],
},
];{
accessorKey: 'name',
header: 'Name',
size: 200,
}{
accessorKey: 'price',
header: 'Price',
meta: {
cellAlign: 'right',
valueFormatter: (value) => `$${value.toFixed(2)}`,
},
}{
accessorKey: 'status',
header: 'Status',
cell: ({ getValue }) => (
<BadgeCell
value={getValue()}
variant={getValue() === 'active' ? 'default' : 'secondary'}
/>
),
}{
id: 'actions',
header: 'Actions',
size: 100,
enableSorting: false,
enableResizing: false,
cell: ({ row }) => (
<div className="flex gap-2">
<Button size="sm" onClick={() => edit(row)}>
Edit
</Button>
<Button size="sm" variant="destructive" onClick={() => del(row)}>
Delete
</Button>
</div>
),
}{
accessorKey: 'quantity',
header: 'Quantity',
meta: {
editable: true,
editType: 'number',
validate: (value) => {
if (value < 0) return 'Must be positive';
return undefined;
},
},
}{
accessorKey: 'category',
header: 'Category',
meta: {
filterType: 'select',
filterOptions: [
{ label: 'Electronics', value: 'electronics' },
{ label: 'Clothing', value: 'clothing' },
{ label: 'Books', value: 'books' },
],
},
}const fieldNames = ['name', 'email', 'phone'];
const columns = fieldNames.map(field => ({
accessorKey: field,
header: field.charAt(0).toUpperCase() + field.slice(1),
}));const columns: GridColumnDef<User>[] = [
{
accessorKey: 'name',
header: 'Name',
},
{
accessorKey: 'email',
header: 'Email',
},
...(userIsAdmin ? [{
id: 'admin-actions',
header: 'Admin Actions',
cell: ({ row }) => <AdminActions row={row} />,
}] : []),
];import { ColumnVisibilityState } from '@tanstack/react-table';
const [columnVisibility, setColumnVisibility] = useState<ColumnVisibilityState>({
email: false,
phone: false,
});
<ActiveGrid
columns={columns}
state={{ columnVisibility }}
onColumnVisibilityChange={setColumnVisibility}
{...}
/>import { ColumnOrderState } from '@tanstack/react-table';
const [columnOrder, setColumnOrder] = useState<ColumnOrderState>([
'name',
'email',
'status',
'actions',
]);
<ActiveGrid
columns={columns}
state={{ columnOrder }}
onColumnOrderChange={setColumnOrder}
{...}
/>import { ColumnPinningState } from '@tanstack/react-table';
const [columnPinning, setColumnPinning] = useState<ColumnPinningState>({
left: ['name'],
right: ['actions'],
});
<ActiveGrid
columns={columns}
state={{ columnPinning }}
onColumnPinningChange={setColumnPinning}
{...}
/>const columns = useMemo<GridColumnDef<User>[]>(() => [
{
accessorKey: 'name',
header: 'Name',
},
{
accessorKey: 'email',
header: 'Email',
},
], []);import { GridColumnDef } from '@workspace/active-grid';
type User = {
id: string;
name: string;
email: string;
status: 'active' | 'inactive';
};
const columns: GridColumnDef<User>[] = [
{
accessorKey: 'name',
header: 'Name',
},
{
accessorKey: 'status',
header: 'Status',
cell: ({ getValue }) => {
const status = getValue() as User['status'];
return <BadgeCell value={status} />;
},
},
];