import { BasePlugin } from '../base'; import type { HotInstance } from '../../core/types'; /** * Sort descriptor in query parameters (`fetchRows` and DataProvider getters). * * @typedef {object} DataProviderSortDescriptor * @property {string} prop Column data key. * @property {'asc'|'desc'} order Sort direction. */ /** * Single filter condition entry (same shape as Filters `exportConditions` items). * * @typedef {object} DataProviderFilterCondition * @property {string} [name] Condition name (omitted for some stack entries). * @property {Array<*>} args Condition arguments. */ /** * Server filter column (`prop` replaces physical column index). Same shape as in `types/plugins/dataProvider/dataProvider.d.ts`. * * @typedef {object} DataProviderFilterColumn * @property {string} prop Column data key. * @property {'conjunction'|'disjunction'|'disjunctionWithExtraCondition'} operation Filters stack operation (same values as [[Filters#exportConditions]]). * @property {Array} conditions Filter conditions (same shape as Filters `exportConditions`). */ /** * Query parameters passed to `fetchRows` and exposed by DataProvider. * * @typedef {object} DataProviderQueryParameters * @property {number} page 1-based page index. * @property {number} pageSize Rows per page. * @property {DataProviderSortDescriptor|null} sort Primary sort or null. * @property {Array|null} filters Server-side filters or null. */ export interface DataProviderSortDescriptor { prop: string; order: 'asc' | 'desc'; } export interface DataProviderFilterCondition { name?: string; args: unknown[]; } export interface DataProviderFilterColumn { prop: string; operation: string; conditions: DataProviderFilterCondition[]; } export interface DataProviderQueryParameters { page: number; pageSize: number; sort: DataProviderSortDescriptor | null; filters: DataProviderFilterColumn[] | null; } export interface DataProviderBeforeFetchParameters extends DataProviderQueryParameters { skipLoading?: boolean; } export type DataProviderFetchDataOverrides = Partial & { skipLoading?: boolean; }; export interface DataProviderFetchResult { rows: unknown[]; totalRows: number; queryParameters?: DataProviderQueryParameters; columnSortConfig?: unknown[]; filtersConditionsStack?: unknown[]; } export interface DataProviderFetchOptions { signal: AbortSignal; } /** * @deprecated Use DataProviderFetchOptions */ export type DataProviderOptions = DataProviderFetchOptions; export interface RowsCreatePayload { position: 'above' | 'below'; referenceRowId?: unknown; rowsAmount: number; } export interface RowUpdatePayload { id: unknown; changes: Record; rowData?: Record | unknown[]; } export interface RowMutationCreatePayload { rowsCreate: RowsCreatePayload; } export interface RowMutationUpdatePayload { rows: RowUpdatePayload[]; } export interface RowMutationRemovePayload { rowsRemove: unknown[]; } export type RowMutationPayload = RowMutationCreatePayload | RowMutationUpdatePayload | RowMutationRemovePayload; export interface DataProviderConfig { rowId: string; fetchRows: (queryParameters: DataProviderQueryParameters, options: DataProviderFetchOptions) => Promise; onRowsCreate?: (payload: RowsCreatePayload) => Promise; onRowsUpdate?: (payload: RowUpdatePayload[]) => Promise; onRowsRemove?: (payload: unknown[]) => Promise; } export { PLUGIN_KEY, PLUGIN_PRIORITY, } from './constants'; /** * @plugin DataProvider * @class DataProvider * * @description * A truthy [[Options#dataProvider]] value enables this plugin. Each key (`rowId`, `fetchRows`, `onRowsCreate`, `onRowsUpdate`, `onRowsRemove`) is validated like other plugin options. * When the object is a **complete** server-backed configuration (all of those keys present and valid), Handsontable loads rows via `fetchRows`, runs mutations through the callbacks, and the [[Hooks#hasExternalDataSource]] hook returns `true` so plugins such as Filters and Pagination can treat the grid as server-driven. * If required callbacks are missing or invalid, `fetchRows` and the affected mutation paths no-op until the configuration is valid. * Valid edits apply to the grid immediately; if `onRowsUpdate` fails, if validation fails later, or if `beforeRowsMutation` cancels, those cells revert to their previous values. * When the [[Options#notification]] plugin is enabled, failed `fetchRows`, `onRowsCreate`, `onRowsUpdate`, or `onRowsRemove` requests (including a refetch after a successful mutation) show an error notification toast with the same translated titles and description text as before. * * If `trimRows`, `manualRowMove`, `manualColumnMove`, or `multiColumnSorting` is enabled, the DataProvider plugin does not enable. Handsontable logs a console warning when you still set a complete `dataProvider` configuration. * Use [[Options#columnSorting]] for server-driven sort (single column). Query `sort` uses `prop` (column data key). */ export declare class DataProvider extends BasePlugin { #private; /** * Returns the plugin key used to identify this plugin in Handsontable settings. */ static get PLUGIN_KEY(): string; /** * Returns the priority order used to determine the order in which plugins are initialized. */ static get PLUGIN_PRIORITY(): number; /** * Returns the setting keys that trigger a plugin update when changed via `updateSettings`. */ static get SETTING_KEYS(): string[]; /** * Returns the default settings applied when the plugin is enabled without explicit configuration. */ static get DEFAULT_SETTINGS(): { rowId: string | ((rowData: unknown) => unknown) | undefined; fetchRows: DataProviderConfig["fetchRows"] | undefined; onRowsCreate: DataProviderConfig["onRowsCreate"] | undefined; onRowsUpdate: DataProviderConfig["onRowsUpdate"] | undefined; onRowsRemove: DataProviderConfig["onRowsRemove"] | undefined; }; /** * Returns validator functions for each plugin setting to verify their values are valid before applying them. */ static get SETTINGS_VALIDATORS(): Record boolean>; /** * @param {object} hotInstance Handsontable instance. */ constructor(hotInstance: HotInstance); /** * Check if the plugin is enabled in the handsontable settings. * * @returns {boolean} */ isEnabled(): boolean; /** * Enables the plugin, syncs query parameters from Pagination, ColumnSorting, and Filters, and registers hooks. */ enablePlugin(): void; /** * Re-applies settings and refetches when the instance is already initialized. */ updatePlugin(): void; /** * Disables the plugin, aborts fetch, resets query state. * Hook listeners registered with `addHook` are removed by `super.disablePlugin()` via `clearHooks()`. * The constructor registers [[Hooks#hasExternalDataSource]] for the period before the first `enablePlugin()`; * `enablePlugin()` registers it again so it survives each `updatePlugin()` cycle. */ disablePlugin(): void; /** * @returns {DataProviderQueryParameters} Copy of current query parameters (`sort` and `filters` are cloned when non-null). */ getQueryParameters(): DataProviderQueryParameters; /** * @param {number} visualRow Visual row index. * @returns {*} Row id from `rowId` option, or undefined. */ getRowId(visualRow: number): unknown; /** * Fetches rows from `fetchRows` with current or overridden query parameters. * * @param {object} [overrides] Partial query overrides (e.g. `{ page: 2 }`, `{ pageSize: 20, page: 1 }`, `{ sort }`, `{ filters }`). * Pass `{ skipLoading: true }` to mark internal refetches (for example sort or CRUD); [[Hooks#beforeDataProviderFetch]] receives it, and it is not passed to `fetchRows`. * Numeric `page` is clamped to at least 1. * When the response `totalRows` implies fewer pages than the requested `page`, fetches again at the last valid page without applying the out-of-range result (avoids redundant `afterPageChange` loads and aborted duplicate requests after row removal on the last page). * @returns {Promise<{ rows: Array<*>, totalRows: number }|null>} * * @fires Hooks#afterDataProviderFetch when data loads. * @fires Hooks#afterDataProviderFetchError when `fetchRows` throws a non-abort error. * @fires Hooks#afterDataProviderFetchAbort when the request is superseded, aborted, or ends with `AbortError`. */ fetchData(overrides?: DataProviderFetchDataOverrides): Promise<{ rows: unknown[]; totalRows: number; } | null>; /** * Server create via `onRowsCreate`. Use `rowsAmount` to insert more than one row in one call. * * @param {object} [options] `position`, `referenceRowId`, `rowsAmount`. * @returns {Promise} */ createRows(options?: { position?: string; referenceRowId?: unknown; rowsAmount?: number; }): Promise; /** * Server remove via `onRowsRemove`. Pass one row id or an array of ids. * * After a successful `onRowsRemove`, refetches from the server. When the remove clears every row currently * loaded (typical when emptying the last page) and the current page is greater than 1, loads the previous page * in one request. Otherwise refetches the current page, then loads the previous page when that response is empty * and the current page is still greater than 1. * * @param {Array<*>|*} rowIds Row id or ids. * @returns {Promise} * @throws {Error} When any id is `null` or `undefined`. */ removeRows(rowIds: unknown[] | unknown): Promise; /** * Server update via `onRowsUpdate`. Pass an array of `{ id, changes, rowData? }` (same shape as `onRowsUpdate`). * * @param {object[]} rows Row update payloads (one or more). * @returns {Promise} * @throws {Error} When any payload omits `id` or `id` is `null`. */ updateRows(rows: Array<{ id?: unknown; changes?: Record; rowData?: Record; }>): Promise; /** * Destroys the plugin. */ destroy(): void; }