Columns
Column definitions
Describe each column once, with a key, a header and a type, and the grid handles display, sorting, filtering and export.
A grid takes columns, an array of column definitions in display order. Each definition names the row field to read (key), the title to show (header), and a type that decides how the value is formatted, aligned, sorted and filtered. Everything else, such as width, pinning, tooltips and editing, is an optional field on the same object.
Sort a column from its header, hover a cut-off value for its tooltip, or drag a header edge to resize:
The shape of a column
<script lang="ts">
import { Grid, type ColumnDef } from 'bo-grid';
const columns: ColumnDef[] = [
{ type: 'text', key: 'symbol', header: 'Symbol', sub: 'name', width: 170 },
{ type: 'price', key: 'price', header: 'Price', width: 96 },
{ type: 'percent', key: 'change', header: 'Chg %', width: 90 },
{ type: 'volume', key: 'volume', header: 'Volume', width: 100 },
{ type: 'text', key: 'sector', header: 'Sector', flex: 1 },
];
let rows = $state([
{ id: 1, symbol: 'VNM', name: 'Vinamilk', price: 68.5, change: 1.2, volume: 1_204_000, sector: 'Consumer' },
]);
</script>
<Grid {rows} {columns} height={400} /> keyis the row field the column reads. It is also the column’s identity: sorting, filtering, hiding and saved layouts refer to columns by key, so keep keys unique.headeris the title in the header row.typepicks the cell’s format and behaviour.ColumnDefis a union ontype, so TypeScript checks each type’s own options (decimalsonnumber,minandmaxonheatmap,currencyoncurrency). See Column types for the full list.- Rows are plain objects with a unique
id: a number, or a string such as a symbol or UUID. If your data has another identity field, passgetRowIdinstead of copying it intoid.
Widths
A column is either fixed or flexible:
widthsets a fixed width in pixels.flexsets a grow weight: flex columns share the width that fixed columns leave over, in proportion to their weights. A column withflexignoreswidth.minWidthandmaxWidthbound what a drag-resize can do.
To make every column scale with the grid instead, set fitColumns on the grid. Column sizing covers resizing, fitColumns and autoWidth.
Alignment, classes and formatting
Number types line up on the right and the rest on the left. Set align to override that for one column, for example a custom column that holds numbers.
format(value, row) replaces the built-in formatter. It applies wherever the value is shown as text: the cell, its tooltip, copy and formatted export.
{ type: 'number', key: 'ratio', header: 'Ratio', format: (v) => `${Number(v).toFixed(1)}×` } cellClass and headerClass add your own classes. cellClass can be a function of the value and the row. Rows render inside the grid, so target the classes with :global(...); see Row styles.
Defaults for every column
defaultColumn sets fields that every column starts from. A column’s own fields, and a registered cellType, win over it:
<Grid {rows} {columns} defaultColumn={{ tooltip: true, minWidth: 64, resizable: false }} height={480} /> To reuse a whole kind of column across grids, such as a money amount or an order status, register it once with cellTypes: see Registered cell types.
Locale
Built-in number, price, currency and date formatting uses en-US by default. Set the grid’s locale to change it for every column, or a column’s own locale to change one:
<Grid {rows} {columns} locale="vi-VN" height={480} /> Localization covers the grid’s own strings too.
Reference
key* string Field on the row to read for this column's value. Also the column's id: sort, filter, width and hidden state are keyed by it.
header* string The column's title in the header row.
width number Default 96Width in px. A flex column starts from it where columns have fixed widths (pinned columns, virtualizeColumns), and fitColumns scales columns in proportion to it.
flex number Default undefinedflex-grow weight: the column stretches to fill the space the fixed-width columns leave, shared by weight. When the columns no longer fit, the grid scrolls sideways, counting a flex column as its width, else its minWidth, else 64 px. Unset, the column keeps its width.
minWidth number Default 48Smallest width (px) a drag-resize or autosize can give this column; never less than 48. Under fitColumns, also the narrowest the column gets before the grid scrolls sideways (64 px without one, or the column's width if smaller).
maxWidth number Default InfinityLargest width (px) a drag-resize, an autosize, autoWidth or fitColumns can give this column.
align Align Default 'right' for number types, 'left' for the restWhich side the header, cells and footer sit on. Set it to line a custom column's values up under its title.
Example
{ type: 'custom', key: 'pnl', header: 'P&L', align: 'right' }format (value: unknown, row?: GridRow) => string Custom display formatter, overriding the built-in type formatter. Applies to display, tooltip, copy and (formatted) export. row is absent for aggregate cells.
Example
{ type: 'number', key: 'qty', header: 'Qty', format: (v) => Number(v).toLocaleString('vi-VN') }cellClass string | ((value: unknown, row: GridRow) => string | undefined) Default undefinedExtra class(es) for this column's data cells — a static string, or a function of the cell value/row for conditional styling. Target via :global(.bo-grid .c.your-class).
Example
{ type: 'price', key: 'last', header: 'Last', cellClass: (v, row) => (Number(v) >= Number(row.ceiling) ? 'at-ceiling' : undefined) }headerClass string Default undefinedExtra class(es) for this column's header. Target via :global.
sortable boolean Default trueSet false to disable header-click sorting on this column.
locale string Default undefinedBCP 47 locale for this column's built-in formatting (price, date, currency, relative). Unset, the grid's locale, then en-US.
columns* ColumnDef[] The columns, in display order. A column's type picks how its values show, sort and filter.
Example
const columns: ColumnDef[] = [
{ type: 'text', key: 'sym', header: 'Symbol', width: 90 },
{ type: 'price', key: 'last', header: 'Last', flash: 'auto' },
];defaultColumn DefaultColumn Default undefinedSettings applied under every column — its own fields (and a registered cellType) win.
Example
<Grid {rows} {columns} height={480} defaultColumn={{ minWidth: 72, sortable: false }} />getRowId (row: GridRow) => string | number Default (row) => row.idIdentity key for rows: selection, focus, pins and flashes follow it. Override for string/UUID/composite keys.
Example
<Grid {rows} {columns} height={480} getRowId={(row) => `${row.account}:${row.sym}`} />locale string Default undefinedBCP 47 locale for the grid's own number formatting (aggregation bar, pager row count), and the default for each column's locale. Unset, the runtime's locale.