Server-side configuration
Server-side configuration
How to wire dataProvider with pagination, sorting, and filters, and what fetchRows receives in each request. Start with Server-side data if you need the overview or demo.
Required configuration sketch
dataProvider: { rowId: 'id', // or (row) => row.id fetchRows: async (queryParameters, { signal }) => { // queryParameters: { page, pageSize, sort, filters } const res = await fetch(buildUrl(queryParameters), { signal }); const json = await res.json();
return { rows: json.data, totalRows: json.total }; }, onRowsCreate: async (payload) => { /* POST */ }, onRowsUpdate: async (rows) => { /* PATCH */ }, onRowsRemove: async (rowIds) => { /* DELETE */ },},pagination: { pageSize: 10 }, // or `true`; `pageSize` is read from Pagination into `fetchRows` queryParameters (not a dataProvider key)columnSorting: true, // server-side sort (one column)filters: true, // server-side column filters; read queryParameters.filters in fetchRowsemptyDataState: true, // loading spinner and empty overlay while fetching / when no rowsdialog: true, // built-in error modal when fetchRows or CRUD callbacks reject (including refetch after mutation)Use pagination so users can change pages and page size in the UI. With DataProvider, the Pagination plugin copies its pageSize and current page into every fetchRows call as queryParameters.pageSize and queryParameters.page (including initialPage when that is how the UI selects the first page). There is no pageSize field on the dataProvider object; set rows per page with pagination: { pageSize: 10 }, or pagination: true for the plugin’s default page size. With rowHeaders enabled, the DataProvider plugin uses modifyRowHeader so row headers reflect a global 1-based row index across pages (for example row 0 on page 2 with pageSize: 5 shows header 6), not only the index within the loaded slice. See the Rows pagination guide for the full configuration object.
The sketch also sets filters for server-driven column filters, emptyDataState for loading and empty overlays with asynchronous fetches, and dialog so request failures from the DataProvider can show an error message in the Dialog plugin (see Fetching, hooks, and examples). Omit or adjust any of these if you do not need that feature.
Query parameters
fetchRows receives:
| Field | Type | Description |
|---|---|---|
page | number | 1-based page index. |
pageSize | number | Rows per page: same value as the Pagination plugin’s pageSize setting when Pagination is enabled. |
sort | object or null | Object with prop (column data key) and order ('asc' or 'desc'). null when unsorted. |
filters | array or null | Server-side filter payload when the Filters plugin runs in server mode (same condition shapes as the Filters API, with prop instead of a column index). |
page and pageSize come from the Pagination plugin when it is enabled, including pagination: { pageSize: n } so your API receives n rows per request. If you omit pagination or leave Pagination off, Handsontable still calls fetchRows with a fixed page 1 and the library default page size (10) until you enable pagination or drive pages yourself via fetchData (you can pass { pageSize: n } there as an override).
Respect signal so outdated requests abort when the user sorts, filters, or changes pages quickly.
Sorting and filtering
- Use
columnSortingfor server-backed sorting. IfmultiColumnSortingis enabled, the DataProvider plugin does not run (see Plugins and options that conflict with DataProvider); keep it off for server-driven data. - Enable
filtersand export conditions from the UI; whenfetchRowsis configured, Handsontable maps those conditions intoqueryParameters.filters, resets to page 1, and refetches (Filters skip client-side row trimming). If Filters are on butfetchRowsis missing (incompletedataProviderobject), filtering stays client-side on whatever rows are currently loaded. - With a complete
dataProviderconfiguration, the column menu does not offer Filter by value (only the current page is loaded, so value lists would be incomplete). Use condition-based filters (for example text, numeric, or date conditions) for server-side filtering. ProgrammaticaddCondition(..., 'by_value', ...)is ignored when server-backedfetchRowsis active.