Grid
import { Grid } from 'cx/widgets'; Copied The Grid widget displays tabular data with features like fixed headers, single and multiple selection modes, sorting, filtering, grouping, aggregation, rich cell content, tree columns, and more.
<div controller={PageController}>
<Grid
records={m.records}
style="height: 400px"
scrollable
columns={[
{ header: "Name", field: "fullName", sortable: true },
{ header: "Continent", field: "continent", sortable: true },
{ header: "Browser", field: "browser", sortable: true },
{ header: "OS", field: "os", sortable: true },
{
header: "Visits",
field: "visits",
sortable: true,
align: "right",
},
]}
selection={{
type: KeySelection,
bind: m.selection,
keyField: "id",
multiple: true,
}}
/>
</div> | Name | Continent | Browser | OS | Visits |
|---|---|---|---|---|
| John Doe | Europe | Chrome | Windows | 11 |
| Jane Smith | North America | Firefox | macOS | 37 |
| Bob Wilson | Asia | Safari | Linux | 12 |
| Alice Brown | Africa | Edge | iOS | 99 |
| Charlie Davis | Australia | Chrome | Android | 28 |
| John Doe | Europe | Firefox | Windows | 54 |
| Jane Smith | North America | Safari | macOS | 81 |
| Bob Wilson | Asia | Edge | Linux | 84 |
| Alice Brown | Africa | Chrome | iOS | 53 |
| Charlie Davis | Australia | Firefox | Android | 59 |
| John Doe | Europe | Safari | Windows | 62 |
| Jane Smith | North America | Edge | macOS | 48 |
| Bob Wilson | Asia | Chrome | Linux | 89 |
| Alice Brown | Africa | Firefox | iOS | 17 |
| Charlie Davis | Australia | Safari | Android | 55 |
| John Doe | Europe | Edge | Windows | 93 |
| Jane Smith | North America | Chrome | macOS | 74 |
| Bob Wilson | Asia | Firefox | Linux | 93 |
| Alice Brown | Africa | Safari | iOS | 44 |
| Charlie Davis | Australia | Edge | Android | 77 |
Click on column headers to sort. Hold Ctrl (or Cmd on macOS) and click to select multiple rows.
Columns
Columns define what data is displayed and how. The simplest column configuration uses the field property to display a record property:
columns={[
{ header: "Name", field: "fullName" },
{ header: "Age", field: "age", align: "right" }
]}
For custom cell content, use the children property to render any widget inside the cell. The current record is available via $record:
columns={[
{
header: "Name",
field: "fullName",
children: <strong text={m.$record.fullName} />
},
{
header: "Actions",
children: (
<Button
text="Edit"
onClick={(e, { store }) => {
edit(store.get(m.$record))
}}
/>
)
}
]}
Use value for computed display values while keeping field for sorting:
{
header: "Status",
field: "active",
value: { expr: "{$record.active} ? 'Yes' : 'No'" }
}
Headers
The header property can be a simple string or a configuration object for advanced scenarios like multi-row headers, custom tools, or spanning columns:
columns={[
{
header: {
text: "Name",
colSpan: 2,
align: "center"
},
field: "fullName"
},
{
header: {
text: "Sales",
tool: <Icon name="drop-down" />,
allowSorting: false
},
field: "sales"
}
]}
Use colSpan and rowSpan to create complex multi-row headers. The tool property allows adding custom components like filter dropdowns or menus inside the header.
Dynamic Columns
Use columnParams and onGetColumns to dynamically generate columns based on data or user preferences:
<Grid
records={m.records}
columnParams={m.visibleColumns}
onGetColumns={(params) => {
const baseColumns = [{ header: "Name", field: "name" }];
const dynamicColumns = params.map((col) => ({
header: col.label,
field: col.field,
}));
return [...baseColumns, ...dynamicColumns];
}}
/>
Whenever columnParams changes, onGetColumns is called to recalculate the column configuration. This is useful for user-configurable column visibility, pivot tables, or data-driven column generation.
See also: Complex Headers, Column Resizing, Column Reordering, Fixed Columns, Dynamic Columns
Grouping
Grids support multi-level grouping with aggregates. Define grouping levels using the grouping property:
<Grid
records={m.records}
grouping={[
{
key: { continent: m.$record.continent },
showFooter: true,
},
]}
columns={[
{ header: "Continent", field: "continent" },
{ header: "Name", field: "fullName" },
{
header: "Sales",
field: "sales",
aggregate: "sum",
footer: { tpl: "{$group.sales:n;2}" },
},
]}
/>
Each grouping level supports the following options:
| Property | Type | Description |
|---|---|---|
key | object | Object with name/selector pairs defining how records are grouped. Values are available as $group.keyName. |
showFooter | boolean | Show a footer row with aggregate values after each group. |
showHeader | boolean | Show a header row within each group. Useful for long printable reports. |
showCaption | boolean | Show a caption row at the start of each group. Caption content is defined in the column’s caption property. |
text | string | A selector for text available as $group.$name in templates. |
comparer | function | A function to determine group ordering. |
Column aggregates (sum, count, avg, distinct) are automatically calculated and available in footer/caption templates via $group.
For dynamic grouping, use groupingParams and onGetGrouping:
<Grid
records={m.records}
groupingParams={m.selectedGrouping}
onGetGrouping={(params) => {
if (!params) return null;
return [
{
key: { value: m.$record[params.field] },
showFooter: true,
},
];
}}
columns={columns}
/>
Whenever groupingParams changes, onGetGrouping is called to recalculate the grouping configuration. This allows users to change grouping at runtime.
See also: Grouping, Dynamic Grouping
Drag & Drop
Grids support drag and drop for reordering rows, moving data between grids, and column reordering. Configure dragSource and dropZone to enable this functionality:
<Grid
records={m.records}
dragSource={{ mode: "move", data: { type: "record" } }}
dropZone={{ mode: "insertion" }}
onDrop={(e, { store }) => {
// Handle the drop - reorder records
store.update(m.records, (records) => {
// Move record from e.source.recordIndex to e.target.insertionIndex
});
}}
columns={columns}
/>
The dropZone.mode can be insertion (shows insertion line between rows) or preview (highlights the target row). Use onDropTest to control which drops are allowed.
See also: Row Drag and Drop
Examples
- Searching and Filtering
- Pagination
- Multiple Selection
- Form Edit
- Row Editing
- Cell Editing
- Inline Edit
- Tree Grid
- Stateful TreeGrid
- Header Menu
- Buffering
- Infinite Scrolling
- Row Expanding
Grid Configuration
Data
| Property | Type | Description |
|---|---|---|
records | array | An array of records to be displayed in the grid. |
keyField | string | Field used as unique record identifier. Improves performance on sort by tracking row movement. |
columns | array | An array of column configurations. See Column Configuration below. |
columnParams | any | Parameters passed to onGetColumns for dynamic column generation. |
onGetColumns | function | Callback to dynamically generate columns when columnParams changes. |
recordName | string | Record binding alias. Default is $record. |
recordAlias | string | Alias for recordName. |
dataAdapter | object | Data adapter configuration for grouping and tree operations. |
emptyText | string | Text displayed when grid has no records. |
Selection
| Property | Type | Description |
|---|---|---|
selection | object | Selection configuration. See Selections for details. |
scrollSelectionIntoView | boolean | Scroll selected row into view. Default is false. |
onCreateIsRecordSelectable | function | Callback to create a function that checks if a record is selectable. |
Sorting
| Property | Type | Description |
|---|---|---|
sortField | string | Binding to store the name of the field used for sorting. |
sortDirection | string | Binding to store the sort direction (ASC or DESC). |
sorters | array | Binding to store multiple sorters for server-side sorting. |
preSorters | array | Sorters prepended to the actual list of sorters. |
defaultSortField | string | Default sort field when no sorting is set. |
defaultSortDirection | string | Default sort direction (ASC or DESC). |
remoteSort | boolean | Set to true if sorting is done server-side. |
clearableSort | boolean | Allow clearing sort by clicking header a third time. |
sortOptions | object | Collator options for sorting. See MDN Intl.Collator for available opts. |
Grouping
| Property | Type | Description |
|---|---|---|
grouping | array | An array of grouping level definitions. |
groupingParams | any | Parameters passed to onGetGrouping for dynamic grouping. |
onGetGrouping | function | Callback to dynamically generate grouping when params change. |
preserveGroupOrder | boolean | Keep groups in the same order as source records. |
Filtering
| Property | Type | Description |
|---|---|---|
filterParams | any | Parameters passed to onCreateFilter callback. |
onCreateFilter | function | Callback to create a filter predicate from filterParams. |
Appearance
| Property | Type | Description |
|---|---|---|
scrollable | boolean | Set to true to add a vertical scroll and fixed header. Grid should have height or max-height set. |
border | boolean | Set to true to add default border. Automatically set if scrollable. |
vlines | boolean | Set to true to add vertical gridlines. |
headerMode | string | Header appearance: plain or default. |
showHeader | boolean | Show grid header within groups. Useful for long printable grids. Default is false. |
showFooter | boolean | Show grid footer. Default is false. |
fixedFooter | boolean | Set to true to add a fixed footer at the bottom of the grid. |
rowClass | string | Additional CSS class to be added to each grid row. |
rowStyle | string | object | Additional CSS styles to be added to each grid row. |
Performance
| Property | Type | Description |
|---|---|---|
cached | boolean | Set to true to enable row caching for better performance. |
buffered | boolean | Set to true to render only visible rows. Requires scrollable. |
bufferSize | number | Number of rendered rows in buffered grids. Default is 60. |
bufferStep | number | Number of rows to scroll before buffer recalculation. |
measureRowHeights | boolean | Cache variable row heights in buffered grids. Default is false. |
lockColumnWidths | boolean | Lock column widths after first render. Useful for pagination. |
preciseMeasurements | boolean | Enable sub-pixel measurements. Useful for grids with many columns or small zoom. |
Infinite Scrolling
| Property | Type | Description |
|---|---|---|
infinite | boolean | Enable infinite scrolling. |
onFetchRecords | function | Callback to fetch records during infinite loading. |
Cell Editing
| Property | Type | Description |
|---|---|---|
cellEditable | boolean | Set to true to enable cell editing. Columns must specify editor field. |
onBeforeCellEdit | function | Callback before cell edit. Return false to prevent edit mode. |
onCellEdited | function | Callback after a cell has been successfully edited. |
Focus & Hover
| Property | Type | Description |
|---|---|---|
focusable | boolean | Set to true or false to explicitly control if grid can receive focus. |
hoverChannel | string | Identifier for hover effect synchronization across components. |
rowHoverId | string | number | Unique record identifier within the hover sync group. |
Row Callbacks
| Property | Type | Description |
|---|---|---|
onRowClick | function | Callback executed when a row is clicked. |
onRowDoubleClick | function | Callback executed when a row is double-clicked. |
onRowContextMenu | function | Callback executed when a row is right-clicked. |
onRowKeyDown | function | Callback executed on key down in a focused row. |
Column Callbacks
| Property | Type | Description |
|---|---|---|
onColumnContextMenu | function | Callback executed when a column header is right-clicked. |
onColumnResize | function | Callback executed after a column has been resized. |
Other
| Property | Type | Description |
|---|---|---|
scrollResetParams | any | Parameters whose change will reset scroll position. |
onTrackMappedRecords | function | Callback to track and retrieve displayed (filtered) records. |
onRef | function | Callback to get grid component and instance references on init. |
Column Configuration
| Property | Type | Description |
|---|---|---|
field | string | Name of the property inside the record to display. |
header | string | object | Text or configuration object for the column header. |
format | string | Format string for cell values. |
align | string | Column alignment: left, right, or center. |
sortable | boolean | Set to true to make the column sortable. |
sortField | string | Alternative field used for sorting. |
primarySortDirection | string | Initial sort direction on first click: ASC or DESC. |
aggregate | string | Aggregate function: sum, count, distinct, avg. |
aggregateField | string | Field used for aggregation if different from field. |
footer | string | Value to render in the footer. |
editable | boolean | Indicate if cell is editable. Default is true. |
editor | object | Cell editor configuration. |
draggable | boolean | Make column draggable for reordering. |
resizable | boolean | Make column resizable. |
mergeCells | string | Merge adjacent cells: same-value or always. |
Column Header Configuration
When header is an object, the following properties are available:
| Property | Type | Description |
|---|---|---|
text | string | Header text. |
align | string | Header text alignment: left, right, or center. |
allowSorting | boolean | Enable or disable sorting on the column. Default is true. |
colSpan | number | Number of columns the header cell should span. Default is 1. |
rowSpan | number | Number of rows the header cell should span. Default is 1. |
tool | object | A component rendered inside the header for custom menus or filters. |
resizable | boolean | Set to true to make the column resizable. |
width | number | Binding to store column width after resize. |
tooltip | string | object | Tooltip configuration for the header. |
Drag & Drop Configuration
| Property | Type | Description |
|---|---|---|
dragSource | object | Drag source configuration. Define mode as move or copy and additional data. |
dropZone | object | Drop zone configuration. Define mode as insertion or preview. |
allowsFileDrops | boolean | Allow grid to receive drag and drop operations containing files. |
Drag & Drop Callbacks
onDragStart(e: DragEvent, instance: Instance) - Called when the user starts dragging a row.
e- The native drag event.instance- The grid instance.
onDragEnd(e: DragEvent, instance: Instance) - Called when the user stops dragging.
e- The native drag event.instance- The grid instance.
onDragOver(e: GridDragEvent, instance: Instance): boolean? - Called when the user drags over another item. Return false to prevent dropping.
e- Grid drag event containingsourceandtargetwith record indices.instance- The grid instance.
onDrop(e: GridDragEvent, instance: Instance) - Called when a drop occurs. Use it to update data such as rearranging the list.
e- Grid drag event containingsourceandtargetwith record indices and insertion index.instance- The grid instance.
onDropTest(e: DragEvent, instance: Instance): boolean - Checks whether a drop action is allowed. Return false to reject.
e- The native drag event.instance- The grid instance.
onRowDragOver(e: GridRowDragEvent, instance: Instance): boolean? - Called when dragging over a specific row. Useful for tree grids.
e- Grid row drag event containing source record and target row info.instance- The grid instance.
onRowDrop(e: GridRowDragEvent, instance: Instance): boolean? - Called when dropping onto a row. Use it to attach a node to a subtree.
e- Grid row drag event containing source record and target row info.instance- The grid instance.
onRowDropTest(e: DragEvent, instance: Instance): boolean - Checks whether a row drop action is allowed.
e- The native drag event.instance- The grid instance.
onColumnDrop(e: GridColumnDropEvent, instance: Instance): boolean? - Called when a column is dropped. Use it for column reordering.
e- Column drop event containing column info.instance- The grid instance.
onColumnDropTest(e: DragEvent, instance: Instance): boolean - Checks whether a column drop is valid.
e- The native drag event.instance- The grid instance.
onCreateIsRecordDraggable(): (record) => boolean - Returns a predicate function that determines which records can be dragged.