-
Notifications
You must be signed in to change notification settings - Fork 0
Data Source
📝 Generated from
docs/features/data-source.md. Edit it there; changes made in the wiki are overwritten.
Connect OpenGridX to your backend API so the server does the sorting, filtering and paging.
The dataSource prop is the gateway to server-side operations. The grid calls getRows with a row range and the current sort, filter and aggregation models, and shows the rows it returns. Requests are page-based (see Modes of Operation), not driven by the scroll position.
import { DataGrid, type GridDataSource } from '@opencorestack/opengridx';
const myDataSource: GridDataSource = {
getRows: async (params) => {
const { startRow, endRow, sortModel, filterModel } = params;
const response = await fetch('/api/data', {
method: 'POST',
body: JSON.stringify({ startRow, endRow, sortModel, filterModel })
});
const data = await response.json();
return {
rows: data.items,
rowCount: data.totalCount // the total, used by the pager with paginationMode="server"
};
}
};
<DataGrid
rows={[]}
columns={columns}
dataSource={myDataSource}
pagination
paginationMode="server"
sortingMode="server"
filterMode="server"
/>| Parameter | Type | Description |
|---|---|---|
startRow |
number |
The starting index of the requested range. |
endRow |
number |
The ending index (exclusive): return rows.slice(startRow, endRow). Number.MAX_SAFE_INTEGER means "every row". |
sortModel |
GridSortItem[] |
Current sorting configuration. |
filterModel |
GridFilterModel |
Current filtering configuration. |
groupKeys |
string[] |
Path of the parent whose children are requested (server-side tree data); empty for top-level rows. |
aggregationModel |
GridAggregationModel | undefined |
Current aggregation configuration, so the server can return aggregationResults. |
The grid calls getRows whenever a dataSource is set. Rapid changes are collapsed into one request (300 ms debounce); the loading state shows from the moment a request is scheduled. Rows are keyed with getRowId.
With paginationMode="client" (the default) the grid requests every row once (startRow: 0, endRow: Number.MAX_SAFE_INTEGER) and pages them itself. With sortingMode="server" or filterMode="server" a sort or filter change requests every row again with the new model; client-side sorts and filters, and page changes, never refetch.
Set paginationMode="server". Each page change requests [page * pageSize, (page + 1) * pageSize) and the response replaces the rows. Return rowCount so the pager knows the total.
Row grouping turns pagination off (every group renders in one scrollable view). With rowGroupingModel set, a paginationMode="server" source is therefore asked for every row (startRow: 0, endRow: Number.MAX_SAFE_INTEGER) instead of the first page, and a development warning says so (v3.0+; before, only the first page was requested and the rest were unreachable).
Set paginationMode="infinite" and advance paginationModel.page (for example from onRowsScrollEnd). The grid requests the rows from the end of what is loaded up to the current page and appends them, so a page that moves on while a request is in flight never leaves a gap. See Infinite Scroll.
When treeData is enabled with a dataSource, top-level rows come from the normal request. A row with serverChildrenCount > 0 shows an expand toggle; expanding it calls getRows with that row's path in groupKeys (and startRow: 0, endRow: Number.MAX_SAFE_INTEGER). Return that parent's children. With filterMode="server" / sortingMode="server" the returned rows are neither re-filtered nor re-sorted in the tree. When a refetch replaces the rows (page, sort, filter), the children of nodes that are still expanded are requested again. If a children request fails, the node collapses again and the error is logged; expanding it retries. (It does not show the grid-level error overlay.) defaultGroupingExpansionDepth counts a node with serverChildrenCount > 0 as expandable, so the nodes within that depth (all of them with -1) start expanded and their children are requested right away (v3.0+; before, lazy nodes were never expanded by the default depth).
Models are compared by content, so an inline filterModel={{ items: [] }} or a dataSource={{ getRows }} object recreated with the same getRows function does not refetch. A new getRows function does. A response for parameters that have changed in the meantime is discarded.
If your API call fails, throw an error or return a rejected promise. OpenGridX shows the Error Overlay with the rejection's message (an Error, a string, or any object with a string message) and a Retry button that requests the rows again.
A response the grid cannot use fails the same way (v3.0+): a response without a rows array, or a getRowId that throws for a fetched row, shows the error overlay and ends the loading state, instead of an unhandled promise rejection and an endless "Loading". For a children request (server-side tree data) it collapses the node as a failed request does.
getRows: async () => {
try {
return await apiCall();
} catch (err) {
throw new Error("Failed to connect to database");
}
}OpenGridX 3.2.2 · MIT · This wiki is generated from docs/ on every push to main. To fix a page, open a PR against the source file.
Start here
Components
- DataGrid
- Header
- Row
- Cell
- Toolbar
- Pagination
- Filter Panel
- Tooltip
- Column Visibility
- Column Grouping
- Column Resizing
- Empty State
- Error Overlay
- Aggregation Footer
Features
- Virtualization
- Filtering & Search
- Sorting & Pagination
- Custom Pagination
- Editing & Reordering
- Row Selection
- Clipboard
- Pinning
- State Persistence
- Aggregation & Pivot
- Tree Data & Grouping
- Cell Spanning
- Master-Detail
- Keyboard & Accessibility
- List View
- Infinite Scroll
- Data Source
- Loading States
- Toolbar Customization
- Export (CSV, Excel, JSON, Print)
- PDF Export
Customization
Upgrading
Contributing
- Contributing
- Testing
- Roadmap
- DataGrid orchestration
- GridRowMeta
- useGridControlledState
- useGridRowPipeline
- useGridColumns
- useGridVirtualization
- useGridVisibleRows
- useGridScrollSync
- useGridStateSnapshot