@mui/x-data-grid 8.27.1 → 8.27.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +105 -0
- package/DataGrid/DataGrid.js +7 -0
- package/constants/dataGridPropsDefaultValues.js +1 -0
- package/esm/DataGrid/DataGrid.js +7 -0
- package/esm/constants/dataGridPropsDefaultValues.js +1 -0
- package/esm/hooks/features/dataSource/models.d.ts +4 -1
- package/esm/hooks/features/dataSource/useGridDataSourceBase.d.ts +5 -2
- package/esm/hooks/features/dataSource/useGridDataSourceBase.js +93 -6
- package/esm/hooks/features/editing/useGridRowEditing.js +14 -4
- package/esm/index.js +1 -1
- package/esm/models/api/gridEditingApi.d.ts +0 -1
- package/esm/models/params/gridRowParams.d.ts +0 -1
- package/esm/models/props/DataGridProps.d.ts +7 -0
- package/hooks/features/dataSource/models.d.ts +4 -1
- package/hooks/features/dataSource/useGridDataSourceBase.d.ts +5 -2
- package/hooks/features/dataSource/useGridDataSourceBase.js +92 -5
- package/hooks/features/editing/useGridRowEditing.js +14 -4
- package/index.js +1 -1
- package/models/api/gridEditingApi.d.ts +0 -1
- package/models/params/gridRowParams.d.ts +0 -1
- package/models/props/DataGridProps.d.ts +7 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,111 @@
|
|
|
5
5
|
All notable changes to this project will be documented in this file.
|
|
6
6
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
7
7
|
|
|
8
|
+
## 8.27.3
|
|
9
|
+
|
|
10
|
+
_Feb 25, 2026_
|
|
11
|
+
|
|
12
|
+
We'd like to extend a big thank you to the 4 contributors who made this release possible. Here are some highlights ✨:
|
|
13
|
+
|
|
14
|
+
- 🐞 Bugfixes
|
|
15
|
+
- ⚡️ Improved dynamic data support and cache invalidation in lazy loading for Data Grid Pro
|
|
16
|
+
|
|
17
|
+
The following team members contributed to this release:
|
|
18
|
+
@cherniavskii, @michelengelen, @MBilalShafi, @arminmeh
|
|
19
|
+
|
|
20
|
+
### Data Grid
|
|
21
|
+
|
|
22
|
+
#### `@mui/x-data-grid@8.27.3`
|
|
23
|
+
|
|
24
|
+
- [DataGrid] Preserve key input during row edit when using `rowModesModel` (#21457) @michelengelen
|
|
25
|
+
|
|
26
|
+
#### `@mui/x-data-grid-pro@8.27.3` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
27
|
+
|
|
28
|
+
Same changes as in `@mui/x-data-grid@8.27.3`, plus:
|
|
29
|
+
|
|
30
|
+
- [DataGridPro] Improve dynamic data support and cache invalidation in lazy loading (#21465) @MBilalShafi
|
|
31
|
+
|
|
32
|
+
#### `@mui/x-data-grid-premium@8.27.3` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
33
|
+
|
|
34
|
+
Same changes as in `@mui/x-data-grid-pro@8.27.3`.
|
|
35
|
+
|
|
36
|
+
### Core
|
|
37
|
+
|
|
38
|
+
- [code-infra] Do not append `x` to the last version for the compare API (#21422) @arminmeh
|
|
39
|
+
- [docs-infra] Fix current version detection logic (#21415) @cherniavskii
|
|
40
|
+
|
|
41
|
+
## 8.27.2
|
|
42
|
+
|
|
43
|
+
_Feb 20, 2026_
|
|
44
|
+
|
|
45
|
+
We'd like to extend a big thank you to the 3 contributors who made this release possible. Here are some highlights ✨:
|
|
46
|
+
|
|
47
|
+
- 🐞 Bugfixes
|
|
48
|
+
|
|
49
|
+
### Data Grid
|
|
50
|
+
|
|
51
|
+
#### `@mui/x-data-grid@8.27.2`
|
|
52
|
+
|
|
53
|
+
Internal changes.
|
|
54
|
+
|
|
55
|
+
#### `@mui/x-data-grid-pro@8.27.2` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
56
|
+
|
|
57
|
+
Same changes as in `@mui/x-data-grid@8.27.2`, plus:
|
|
58
|
+
|
|
59
|
+
- [DataGridPro] Fix number input visibility in header filters (#21345) @michelengelen
|
|
60
|
+
|
|
61
|
+
#### `@mui/x-data-grid-premium@8.27.2` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
62
|
+
|
|
63
|
+
Same changes as in `@mui/x-data-grid-pro@8.27.2`.
|
|
64
|
+
|
|
65
|
+
### Date and Time Pickers
|
|
66
|
+
|
|
67
|
+
#### `@mui/x-date-pickers@8.27.2`
|
|
68
|
+
|
|
69
|
+
- [DatePicker] Add keyboard support for selecting day, month, and year (#21399) @michelengelen
|
|
70
|
+
|
|
71
|
+
#### `@mui/x-date-pickers-pro@8.27.2` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
72
|
+
|
|
73
|
+
Same changes as in `@mui/x-date-pickers@8.27.2`, plus:
|
|
74
|
+
|
|
75
|
+
- [DateRangePicker] Fix timezone update issue leading to `invalidRange` error (#21382) @michelengelen
|
|
76
|
+
|
|
77
|
+
### Charts
|
|
78
|
+
|
|
79
|
+
#### `@mui/x-charts@8.27.2`
|
|
80
|
+
|
|
81
|
+
Internal changes.
|
|
82
|
+
|
|
83
|
+
#### `@mui/x-charts-pro@8.27.2` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
84
|
+
|
|
85
|
+
Same changes as in `@mui/x-charts@8.27.2`, plus:
|
|
86
|
+
|
|
87
|
+
- [charts-pro] Handle edge case in export image (#21206) @bernardobelchior
|
|
88
|
+
|
|
89
|
+
#### `@mui/x-charts-premium@8.27.2` [](https://mui.com/r/x-premium-svg-link 'Premium plan')
|
|
90
|
+
|
|
91
|
+
Same changes as in `@mui/x-charts-pro@8.27.2`.
|
|
92
|
+
|
|
93
|
+
### Tree View
|
|
94
|
+
|
|
95
|
+
#### `@mui/x-tree-view@8.27.2`
|
|
96
|
+
|
|
97
|
+
- [tree view] Focus item sibling on unmount instead of the 1st item (#21386) @flaviendelangle
|
|
98
|
+
|
|
99
|
+
#### `@mui/x-tree-view-pro@8.27.2` [](https://mui.com/r/x-pro-svg-link 'Pro plan')
|
|
100
|
+
|
|
101
|
+
Same changes as in `@mui/x-tree-view@8.27.2`.
|
|
102
|
+
|
|
103
|
+
### Codemod
|
|
104
|
+
|
|
105
|
+
#### `@mui/x-codemod@8.27.2`
|
|
106
|
+
|
|
107
|
+
Internal changes.
|
|
108
|
+
|
|
109
|
+
### Core
|
|
110
|
+
|
|
111
|
+
- [code-infra] Only ignore `renovate[bot]` in changelog generation script (#21188) @bernardobelchior
|
|
112
|
+
|
|
8
113
|
## v8.27.1
|
|
9
114
|
|
|
10
115
|
<!-- generated comparing v8.27.0..v8.x -->
|
package/DataGrid/DataGrid.js
CHANGED
|
@@ -180,6 +180,13 @@ DataGridRaw.propTypes = {
|
|
|
180
180
|
get: _propTypes.default.func.isRequired,
|
|
181
181
|
set: _propTypes.default.func.isRequired
|
|
182
182
|
}),
|
|
183
|
+
/**
|
|
184
|
+
* If positive, the Data Grid will periodically revalidate data source rows by
|
|
185
|
+
* re-fetching them from the server when the cache entry has expired.
|
|
186
|
+
* Set to `0` to disable polling.
|
|
187
|
+
* @default 0
|
|
188
|
+
*/
|
|
189
|
+
dataSourceRevalidateMs: _propTypes.default.number,
|
|
183
190
|
/**
|
|
184
191
|
* Set the density of the Data Grid.
|
|
185
192
|
* @default "standard"
|
|
@@ -30,6 +30,7 @@ const DATA_GRID_PROPS_DEFAULT_VALUES = exports.DATA_GRID_PROPS_DEFAULT_VALUES =
|
|
|
30
30
|
disableMultipleColumnsFiltering: false,
|
|
31
31
|
disableMultipleColumnsSorting: false,
|
|
32
32
|
disableMultipleRowSelection: false,
|
|
33
|
+
dataSourceRevalidateMs: 0,
|
|
33
34
|
disableRowSelectionOnClick: false,
|
|
34
35
|
disableRowSelectionExcludeModel: false,
|
|
35
36
|
disableVirtualization: false,
|
package/esm/DataGrid/DataGrid.js
CHANGED
|
@@ -173,6 +173,13 @@ DataGridRaw.propTypes = {
|
|
|
173
173
|
get: PropTypes.func.isRequired,
|
|
174
174
|
set: PropTypes.func.isRequired
|
|
175
175
|
}),
|
|
176
|
+
/**
|
|
177
|
+
* If positive, the Data Grid will periodically revalidate data source rows by
|
|
178
|
+
* re-fetching them from the server when the cache entry has expired.
|
|
179
|
+
* Set to `0` to disable polling.
|
|
180
|
+
* @default 0
|
|
181
|
+
*/
|
|
182
|
+
dataSourceRevalidateMs: PropTypes.number,
|
|
176
183
|
/**
|
|
177
184
|
* Set the density of the Data Grid.
|
|
178
185
|
* @default "standard"
|
|
@@ -24,6 +24,7 @@ export const DATA_GRID_PROPS_DEFAULT_VALUES = {
|
|
|
24
24
|
disableMultipleColumnsFiltering: false,
|
|
25
25
|
disableMultipleColumnsSorting: false,
|
|
26
26
|
disableMultipleRowSelection: false,
|
|
27
|
+
dataSourceRevalidateMs: 0,
|
|
27
28
|
disableRowSelectionOnClick: false,
|
|
28
29
|
disableRowSelectionExcludeModel: false,
|
|
29
30
|
disableVirtualization: false,
|
|
@@ -5,6 +5,9 @@ import type { GridDataSourceCacheDefaultConfig } from "./cache.js";
|
|
|
5
5
|
* The parameters for the `fetchRows` method.
|
|
6
6
|
*/
|
|
7
7
|
export type GridDataSourceFetchRowsParams<T> = Partial<T> & GridGetRowsOptions;
|
|
8
|
+
export interface GridDataSourceFetchRowChildrenOptions {
|
|
9
|
+
showChildrenLoading?: boolean;
|
|
10
|
+
}
|
|
8
11
|
export interface GridDataSourceApi {
|
|
9
12
|
/**
|
|
10
13
|
* The data source API.
|
|
@@ -38,7 +41,7 @@ export interface GridDataSourceApiBase {
|
|
|
38
41
|
}
|
|
39
42
|
export interface GridDataSourceBaseOptions {
|
|
40
43
|
cacheOptions?: GridDataSourceCacheDefaultConfig;
|
|
41
|
-
fetchRowChildren?: (parents: GridRowId[]) => void;
|
|
44
|
+
fetchRowChildren?: (parents: GridRowId[], options?: GridDataSourceFetchRowChildrenOptions) => void;
|
|
42
45
|
clearDataSourceState?: () => void;
|
|
43
46
|
handleEditRow?: (params: GridUpdateRowParams, updatedRow: GridRowModel) => void;
|
|
44
47
|
}
|
|
@@ -6,17 +6,20 @@ import type { GridPrivateApiCommunity } from "../../../models/api/gridApiCommuni
|
|
|
6
6
|
import type { DataGridProcessedProps } from "../../../models/props/DataGridProps.js";
|
|
7
7
|
import type { GridStrategyProcessor } from "../../core/strategyProcessing/index.js";
|
|
8
8
|
import type { GridEventListener } from "../../../models/events/index.js";
|
|
9
|
-
|
|
9
|
+
import type { GridRowId } from "../../../models/gridRows.js";
|
|
10
|
+
export declare const useGridDataSourceBase: <Api extends GridPrivateApiCommunity>(apiRef: RefObject<Api>, props: Pick<DataGridProcessedProps, "dataSource" | "dataSourceCache" | "onDataSourceError" | "pageSizeOptions" | "pagination" | "signature" | "dataSourceRevalidateMs">, options?: GridDataSourceBaseOptions) => {
|
|
10
11
|
api: {
|
|
11
12
|
public: GridDataSourceApi;
|
|
12
13
|
};
|
|
13
|
-
debouncedFetchRows: ((parentId?:
|
|
14
|
+
debouncedFetchRows: ((parentId?: GridRowId, params?: import("./models.js").GridDataSourceFetchRowsParams<import("@mui/x-data-grid").GridGetRowsParams>) => Promise<void>) & import("@mui/utils/debounce").Cancelable;
|
|
14
15
|
strategyProcessor: {
|
|
15
16
|
strategyName: DataSourceRowsUpdateStrategy;
|
|
16
17
|
group: "dataSourceRowsUpdate";
|
|
17
18
|
processor: GridStrategyProcessor<"dataSourceRowsUpdate">;
|
|
18
19
|
};
|
|
19
20
|
setStrategyAvailability: () => void;
|
|
21
|
+
startPolling: () => void;
|
|
22
|
+
stopPolling: () => void;
|
|
20
23
|
cacheChunkManager: CacheChunkManager;
|
|
21
24
|
cache: GridDataSourceCache;
|
|
22
25
|
events: {
|
|
@@ -5,6 +5,7 @@ import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/esm/objectWith
|
|
|
5
5
|
const _excluded = ["skipCache", "keepChildrenExpanded"];
|
|
6
6
|
import * as React from 'react';
|
|
7
7
|
import useLazyRef from '@mui/utils/useLazyRef';
|
|
8
|
+
import useEventCallback from '@mui/utils/useEventCallback';
|
|
8
9
|
import debounce from '@mui/utils/debounce';
|
|
9
10
|
import { warnOnce } from '@mui/x-internals/warning';
|
|
10
11
|
import { isDeepEqual } from '@mui/x-internals/isDeepEqual';
|
|
@@ -12,7 +13,8 @@ import { GRID_ROOT_GROUP_ID } from "../rows/gridRowsUtils.js";
|
|
|
12
13
|
import { runIf } from "../../../utils/utils.js";
|
|
13
14
|
import { GridStrategyGroup } from "../../core/strategyProcessing/index.js";
|
|
14
15
|
import { useGridSelector } from "../../utils/useGridSelector.js";
|
|
15
|
-
import { gridPaginationModelSelector } from "../pagination/gridPaginationSelector.js";
|
|
16
|
+
import { gridPaginationModelSelector, gridVisibleRowsSelector } from "../pagination/gridPaginationSelector.js";
|
|
17
|
+
import { gridRowTreeSelector } from "../rows/gridRowsSelector.js";
|
|
16
18
|
import { gridGetRowsParamsSelector } from "./gridDataSourceSelector.js";
|
|
17
19
|
import { CacheChunkManager, DataSourceRowsUpdateStrategy } from "./utils.js";
|
|
18
20
|
import { GridDataSourceCacheDefault } from "./cache.js";
|
|
@@ -38,7 +40,9 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
38
40
|
}, [currentStrategy]);
|
|
39
41
|
const paginationModel = useGridSelector(apiRef, gridPaginationModelSelector);
|
|
40
42
|
const lastRequestId = React.useRef(0);
|
|
43
|
+
const pollingIntervalRef = React.useRef(null);
|
|
41
44
|
const onDataSourceErrorProp = props.onDataSourceError;
|
|
45
|
+
const revalidateMs = props.dataSourceRevalidateMs;
|
|
42
46
|
const cacheChunkManager = useLazyRef(() => {
|
|
43
47
|
if (!props.pagination) {
|
|
44
48
|
return new CacheChunkManager(paginationModel.pageSize);
|
|
@@ -128,6 +132,69 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
128
132
|
const handleStrategyActivityChange = React.useCallback(() => {
|
|
129
133
|
setCurrentStrategy(apiRef.current.getActiveStrategy(GridStrategyGroup.DataSource));
|
|
130
134
|
}, [apiRef]);
|
|
135
|
+
const fetchRowChildrenOption = options.fetchRowChildren;
|
|
136
|
+
const revalidate = useEventCallback(async () => {
|
|
137
|
+
const getRows = props.dataSource?.getRows;
|
|
138
|
+
if (!getRows || !standardRowsUpdateStrategyActive) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const revalidateExpandedGroups = () => {
|
|
142
|
+
if (currentStrategy !== DataSourceRowsUpdateStrategy.GroupedData || !fetchRowChildrenOption) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
const rowTree = gridRowTreeSelector(apiRef);
|
|
146
|
+
const visibleRows = gridVisibleRowsSelector(apiRef).rows;
|
|
147
|
+
const expandedGroupIds = visibleRows.reduce((acc, row) => {
|
|
148
|
+
const node = rowTree[row.id];
|
|
149
|
+
if (node.type === 'group' && node.id !== GRID_ROOT_GROUP_ID && node.childrenExpanded === true) {
|
|
150
|
+
acc.push(row.id);
|
|
151
|
+
}
|
|
152
|
+
return acc;
|
|
153
|
+
}, []);
|
|
154
|
+
if (expandedGroupIds.length > 0) {
|
|
155
|
+
fetchRowChildrenOption(expandedGroupIds, {
|
|
156
|
+
showChildrenLoading: false
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
};
|
|
160
|
+
const fetchParams = _extends({}, gridGetRowsParamsSelector(apiRef), apiRef.current.unstable_applyPipeProcessors('getRowsParams', {}));
|
|
161
|
+
const cacheKeys = cacheChunkManager.getCacheKeys(fetchParams);
|
|
162
|
+
const responses = cacheKeys.map(cacheKey => cache.get(cacheKey));
|
|
163
|
+
if (responses.every(response => response !== undefined)) {
|
|
164
|
+
revalidateExpandedGroups();
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
try {
|
|
168
|
+
const response = await getRows(fetchParams);
|
|
169
|
+
const currentParams = _extends({}, gridGetRowsParamsSelector(apiRef), apiRef.current.unstable_applyPipeProcessors('getRowsParams', {}));
|
|
170
|
+
if (!isDeepEqual(fetchParams, currentParams)) {
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
const cacheResponses = cacheChunkManager.splitResponse(fetchParams, response);
|
|
174
|
+
cacheResponses.forEach((cacheResponse, key) => cache.set(key, cacheResponse));
|
|
175
|
+
apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
|
|
176
|
+
response,
|
|
177
|
+
fetchParams,
|
|
178
|
+
options: {}
|
|
179
|
+
});
|
|
180
|
+
revalidateExpandedGroups();
|
|
181
|
+
} catch {
|
|
182
|
+
// Ignore background revalidation errors.
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
const stopPolling = React.useCallback(() => {
|
|
186
|
+
if (pollingIntervalRef.current !== null) {
|
|
187
|
+
clearInterval(pollingIntervalRef.current);
|
|
188
|
+
pollingIntervalRef.current = null;
|
|
189
|
+
}
|
|
190
|
+
}, []);
|
|
191
|
+
const startPolling = useEventCallback(() => {
|
|
192
|
+
stopPolling();
|
|
193
|
+
if (revalidateMs <= 0 || !standardRowsUpdateStrategyActive) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
pollingIntervalRef.current = setInterval(revalidate, revalidateMs);
|
|
197
|
+
});
|
|
131
198
|
const handleDataUpdate = React.useCallback(params => {
|
|
132
199
|
if ('error' in params) {
|
|
133
200
|
apiRef.current.setRows([]);
|
|
@@ -144,7 +211,8 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
144
211
|
params: params.fetchParams,
|
|
145
212
|
response
|
|
146
213
|
}, true);
|
|
147
|
-
|
|
214
|
+
startPolling();
|
|
215
|
+
}, [apiRef, startPolling]);
|
|
148
216
|
const dataSourceUpdateRow = props.dataSource?.updateRow;
|
|
149
217
|
const handleEditRowOption = options.handleEditRow;
|
|
150
218
|
const editRow = React.useCallback(async params => {
|
|
@@ -184,6 +252,10 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
184
252
|
}
|
|
185
253
|
};
|
|
186
254
|
const debouncedFetchRows = React.useMemo(() => debounce(fetchRows, 0), [fetchRows]);
|
|
255
|
+
const handleFetchRowsOnParamsChange = React.useCallback(() => {
|
|
256
|
+
stopPolling();
|
|
257
|
+
debouncedFetchRows();
|
|
258
|
+
}, [stopPolling, debouncedFetchRows]);
|
|
187
259
|
const isFirstRender = React.useRef(true);
|
|
188
260
|
React.useEffect(() => {
|
|
189
261
|
if (isFirstRender.current) {
|
|
@@ -196,6 +268,17 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
196
268
|
const newCache = getCache(props.dataSourceCache, options.cacheOptions);
|
|
197
269
|
setCache(prevCache => prevCache !== newCache ? newCache : prevCache);
|
|
198
270
|
}, [props.dataSourceCache, options.cacheOptions]);
|
|
271
|
+
React.useEffect(() => {
|
|
272
|
+
if (!standardRowsUpdateStrategyActive) {
|
|
273
|
+
stopPolling();
|
|
274
|
+
}
|
|
275
|
+
}, [standardRowsUpdateStrategyActive, stopPolling]);
|
|
276
|
+
React.useEffect(() => {
|
|
277
|
+
if (revalidateMs <= 0) {
|
|
278
|
+
stopPolling();
|
|
279
|
+
}
|
|
280
|
+
}, [revalidateMs, stopPolling]);
|
|
281
|
+
React.useEffect(() => stopPolling, [stopPolling]);
|
|
199
282
|
React.useEffect(() => {
|
|
200
283
|
// Return early if the proper strategy isn't set yet
|
|
201
284
|
// Context: https://github.com/mui/mui-x/issues/19650
|
|
@@ -203,6 +286,8 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
203
286
|
return undefined;
|
|
204
287
|
}
|
|
205
288
|
if (props.dataSource) {
|
|
289
|
+
stopPolling();
|
|
290
|
+
apiRef.current.setRows([]);
|
|
206
291
|
apiRef.current.dataSource.cache.clear();
|
|
207
292
|
apiRef.current.dataSource.fetchRows();
|
|
208
293
|
}
|
|
@@ -210,7 +295,7 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
210
295
|
// ignore the current request on unmount
|
|
211
296
|
lastRequestId.current += 1;
|
|
212
297
|
};
|
|
213
|
-
}, [apiRef, props.dataSource, currentStrategy]);
|
|
298
|
+
}, [apiRef, props.dataSource, currentStrategy, stopPolling]);
|
|
214
299
|
return {
|
|
215
300
|
api: {
|
|
216
301
|
public: dataSourceApi
|
|
@@ -222,13 +307,15 @@ export const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
222
307
|
processor: handleDataUpdate
|
|
223
308
|
},
|
|
224
309
|
setStrategyAvailability,
|
|
310
|
+
startPolling,
|
|
311
|
+
stopPolling,
|
|
225
312
|
cacheChunkManager,
|
|
226
313
|
cache,
|
|
227
314
|
events: {
|
|
228
315
|
strategyAvailabilityChange: handleStrategyActivityChange,
|
|
229
|
-
sortModelChange: runIf(standardRowsUpdateStrategyActive,
|
|
230
|
-
filterModelChange: runIf(standardRowsUpdateStrategyActive,
|
|
231
|
-
paginationModelChange: runIf(standardRowsUpdateStrategyActive,
|
|
316
|
+
sortModelChange: runIf(standardRowsUpdateStrategyActive, handleFetchRowsOnParamsChange),
|
|
317
|
+
filterModelChange: runIf(standardRowsUpdateStrategyActive, handleFetchRowsOnParamsChange),
|
|
318
|
+
paginationModelChange: runIf(standardRowsUpdateStrategyActive, handleFetchRowsOnParamsChange)
|
|
232
319
|
}
|
|
233
320
|
};
|
|
234
321
|
};
|
|
@@ -184,12 +184,15 @@ export const useGridRowEditing = (apiRef, props) => {
|
|
|
184
184
|
const rowParams = apiRef.current.getRowParams(params.id);
|
|
185
185
|
const newParams = _extends({}, rowParams, {
|
|
186
186
|
field: params.field,
|
|
187
|
-
reason
|
|
187
|
+
reason,
|
|
188
|
+
// Only pass the pressed key when the row editing is controlled via `rowModesModel`.
|
|
189
|
+
// In uncontrolled mode, the default editor already inserts the character and passing it here would duplicate it.
|
|
190
|
+
key: rowModesModelProp && isPrintableKey(event) ? event.key : undefined
|
|
188
191
|
});
|
|
189
192
|
apiRef.current.publishEvent('rowEditStart', newParams, event);
|
|
190
193
|
}
|
|
191
194
|
}
|
|
192
|
-
}, [apiRef, hasFieldsWithErrors]);
|
|
195
|
+
}, [apiRef, hasFieldsWithErrors, rowModesModelProp]);
|
|
193
196
|
const handleRowEditStart = React.useCallback(params => {
|
|
194
197
|
const {
|
|
195
198
|
id,
|
|
@@ -201,10 +204,17 @@ export const useGridRowEditing = (apiRef, props) => {
|
|
|
201
204
|
fieldToFocus: field
|
|
202
205
|
};
|
|
203
206
|
if (reason === GridRowEditStartReasons.printableKeyDown || reason === GridRowEditStartReasons.deleteKeyDown) {
|
|
204
|
-
|
|
207
|
+
// If the user typed a printable key, initialize the value with that key
|
|
208
|
+
// to avoid losing the first character when the component is controlled.
|
|
209
|
+
if (rowModesModelProp && reason === GridRowEditStartReasons.printableKeyDown && params.key && field) {
|
|
210
|
+
startRowEditModeParams.initialValue = params.key;
|
|
211
|
+
} else {
|
|
212
|
+
// For Delete / Backspace or for uncontrolled row editing we clear the value
|
|
213
|
+
startRowEditModeParams.deleteValue = !!field;
|
|
214
|
+
}
|
|
205
215
|
}
|
|
206
216
|
apiRef.current.startRowEditMode(startRowEditModeParams);
|
|
207
|
-
}, [apiRef]);
|
|
217
|
+
}, [apiRef, rowModesModelProp]);
|
|
208
218
|
const handleRowEditStop = React.useCallback(params => {
|
|
209
219
|
const {
|
|
210
220
|
id,
|
package/esm/index.js
CHANGED
|
@@ -73,7 +73,6 @@ export interface GridRowEditStartParams<R extends GridValidRowModel = any> exten
|
|
|
73
73
|
reason?: GridRowEditStartReasons;
|
|
74
74
|
/**
|
|
75
75
|
* If the reason is related to a keyboard event, it contains which key was pressed.
|
|
76
|
-
* @deprecated No longer needed.
|
|
77
76
|
*/
|
|
78
77
|
key?: string;
|
|
79
78
|
}
|
|
@@ -325,6 +325,13 @@ export interface DataGridPropsWithDefaultValues<R extends GridValidRowModel = an
|
|
|
325
325
|
* @default 0
|
|
326
326
|
*/
|
|
327
327
|
throttleRowsMs: number;
|
|
328
|
+
/**
|
|
329
|
+
* If positive, the Data Grid will periodically revalidate data source rows by re-fetching them from the server when the cache entry has expired.
|
|
330
|
+
* If the refetched rows are different from the current rows, the grid will update the rows.
|
|
331
|
+
* Set to `0` to disable polling.
|
|
332
|
+
* @default 0
|
|
333
|
+
*/
|
|
334
|
+
dataSourceRevalidateMs: number;
|
|
328
335
|
/**
|
|
329
336
|
* If `true`, reordering columns is disabled.
|
|
330
337
|
* @default false
|
|
@@ -5,6 +5,9 @@ import type { GridDataSourceCacheDefaultConfig } from "./cache.js";
|
|
|
5
5
|
* The parameters for the `fetchRows` method.
|
|
6
6
|
*/
|
|
7
7
|
export type GridDataSourceFetchRowsParams<T> = Partial<T> & GridGetRowsOptions;
|
|
8
|
+
export interface GridDataSourceFetchRowChildrenOptions {
|
|
9
|
+
showChildrenLoading?: boolean;
|
|
10
|
+
}
|
|
8
11
|
export interface GridDataSourceApi {
|
|
9
12
|
/**
|
|
10
13
|
* The data source API.
|
|
@@ -38,7 +41,7 @@ export interface GridDataSourceApiBase {
|
|
|
38
41
|
}
|
|
39
42
|
export interface GridDataSourceBaseOptions {
|
|
40
43
|
cacheOptions?: GridDataSourceCacheDefaultConfig;
|
|
41
|
-
fetchRowChildren?: (parents: GridRowId[]) => void;
|
|
44
|
+
fetchRowChildren?: (parents: GridRowId[], options?: GridDataSourceFetchRowChildrenOptions) => void;
|
|
42
45
|
clearDataSourceState?: () => void;
|
|
43
46
|
handleEditRow?: (params: GridUpdateRowParams, updatedRow: GridRowModel) => void;
|
|
44
47
|
}
|
|
@@ -6,17 +6,20 @@ import type { GridPrivateApiCommunity } from "../../../models/api/gridApiCommuni
|
|
|
6
6
|
import type { DataGridProcessedProps } from "../../../models/props/DataGridProps.js";
|
|
7
7
|
import type { GridStrategyProcessor } from "../../core/strategyProcessing/index.js";
|
|
8
8
|
import type { GridEventListener } from "../../../models/events/index.js";
|
|
9
|
-
|
|
9
|
+
import type { GridRowId } from "../../../models/gridRows.js";
|
|
10
|
+
export declare const useGridDataSourceBase: <Api extends GridPrivateApiCommunity>(apiRef: RefObject<Api>, props: Pick<DataGridProcessedProps, "dataSource" | "dataSourceCache" | "onDataSourceError" | "pageSizeOptions" | "pagination" | "signature" | "dataSourceRevalidateMs">, options?: GridDataSourceBaseOptions) => {
|
|
10
11
|
api: {
|
|
11
12
|
public: GridDataSourceApi;
|
|
12
13
|
};
|
|
13
|
-
debouncedFetchRows: ((parentId?:
|
|
14
|
+
debouncedFetchRows: ((parentId?: GridRowId, params?: import("./models.js").GridDataSourceFetchRowsParams<import("@mui/x-data-grid").GridGetRowsParams>) => Promise<void>) & import("@mui/utils/debounce").Cancelable;
|
|
14
15
|
strategyProcessor: {
|
|
15
16
|
strategyName: DataSourceRowsUpdateStrategy;
|
|
16
17
|
group: "dataSourceRowsUpdate";
|
|
17
18
|
processor: GridStrategyProcessor<"dataSourceRowsUpdate">;
|
|
18
19
|
};
|
|
19
20
|
setStrategyAvailability: () => void;
|
|
21
|
+
startPolling: () => void;
|
|
22
|
+
stopPolling: () => void;
|
|
20
23
|
cacheChunkManager: CacheChunkManager;
|
|
21
24
|
cache: GridDataSourceCache;
|
|
22
25
|
events: {
|
|
@@ -11,6 +11,7 @@ var _extends2 = _interopRequireDefault(require("@babel/runtime/helpers/extends")
|
|
|
11
11
|
var _objectWithoutPropertiesLoose2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutPropertiesLoose"));
|
|
12
12
|
var React = _interopRequireWildcard(require("react"));
|
|
13
13
|
var _useLazyRef = _interopRequireDefault(require("@mui/utils/useLazyRef"));
|
|
14
|
+
var _useEventCallback = _interopRequireDefault(require("@mui/utils/useEventCallback"));
|
|
14
15
|
var _debounce = _interopRequireDefault(require("@mui/utils/debounce"));
|
|
15
16
|
var _warning = require("@mui/x-internals/warning");
|
|
16
17
|
var _isDeepEqual = require("@mui/x-internals/isDeepEqual");
|
|
@@ -19,6 +20,7 @@ var _utils = require("../../../utils/utils");
|
|
|
19
20
|
var _strategyProcessing = require("../../core/strategyProcessing");
|
|
20
21
|
var _useGridSelector = require("../../utils/useGridSelector");
|
|
21
22
|
var _gridPaginationSelector = require("../pagination/gridPaginationSelector");
|
|
23
|
+
var _gridRowsSelector = require("../rows/gridRowsSelector");
|
|
22
24
|
var _gridDataSourceSelector = require("./gridDataSourceSelector");
|
|
23
25
|
var _utils2 = require("./utils");
|
|
24
26
|
var _cache = require("./cache");
|
|
@@ -45,7 +47,9 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
45
47
|
}, [currentStrategy]);
|
|
46
48
|
const paginationModel = (0, _useGridSelector.useGridSelector)(apiRef, _gridPaginationSelector.gridPaginationModelSelector);
|
|
47
49
|
const lastRequestId = React.useRef(0);
|
|
50
|
+
const pollingIntervalRef = React.useRef(null);
|
|
48
51
|
const onDataSourceErrorProp = props.onDataSourceError;
|
|
52
|
+
const revalidateMs = props.dataSourceRevalidateMs;
|
|
49
53
|
const cacheChunkManager = (0, _useLazyRef.default)(() => {
|
|
50
54
|
if (!props.pagination) {
|
|
51
55
|
return new _utils2.CacheChunkManager(paginationModel.pageSize);
|
|
@@ -135,6 +139,69 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
135
139
|
const handleStrategyActivityChange = React.useCallback(() => {
|
|
136
140
|
setCurrentStrategy(apiRef.current.getActiveStrategy(_strategyProcessing.GridStrategyGroup.DataSource));
|
|
137
141
|
}, [apiRef]);
|
|
142
|
+
const fetchRowChildrenOption = options.fetchRowChildren;
|
|
143
|
+
const revalidate = (0, _useEventCallback.default)(async () => {
|
|
144
|
+
const getRows = props.dataSource?.getRows;
|
|
145
|
+
if (!getRows || !standardRowsUpdateStrategyActive) {
|
|
146
|
+
return;
|
|
147
|
+
}
|
|
148
|
+
const revalidateExpandedGroups = () => {
|
|
149
|
+
if (currentStrategy !== _utils2.DataSourceRowsUpdateStrategy.GroupedData || !fetchRowChildrenOption) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const rowTree = (0, _gridRowsSelector.gridRowTreeSelector)(apiRef);
|
|
153
|
+
const visibleRows = (0, _gridPaginationSelector.gridVisibleRowsSelector)(apiRef).rows;
|
|
154
|
+
const expandedGroupIds = visibleRows.reduce((acc, row) => {
|
|
155
|
+
const node = rowTree[row.id];
|
|
156
|
+
if (node.type === 'group' && node.id !== _gridRowsUtils.GRID_ROOT_GROUP_ID && node.childrenExpanded === true) {
|
|
157
|
+
acc.push(row.id);
|
|
158
|
+
}
|
|
159
|
+
return acc;
|
|
160
|
+
}, []);
|
|
161
|
+
if (expandedGroupIds.length > 0) {
|
|
162
|
+
fetchRowChildrenOption(expandedGroupIds, {
|
|
163
|
+
showChildrenLoading: false
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
const fetchParams = (0, _extends2.default)({}, (0, _gridDataSourceSelector.gridGetRowsParamsSelector)(apiRef), apiRef.current.unstable_applyPipeProcessors('getRowsParams', {}));
|
|
168
|
+
const cacheKeys = cacheChunkManager.getCacheKeys(fetchParams);
|
|
169
|
+
const responses = cacheKeys.map(cacheKey => cache.get(cacheKey));
|
|
170
|
+
if (responses.every(response => response !== undefined)) {
|
|
171
|
+
revalidateExpandedGroups();
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
try {
|
|
175
|
+
const response = await getRows(fetchParams);
|
|
176
|
+
const currentParams = (0, _extends2.default)({}, (0, _gridDataSourceSelector.gridGetRowsParamsSelector)(apiRef), apiRef.current.unstable_applyPipeProcessors('getRowsParams', {}));
|
|
177
|
+
if (!(0, _isDeepEqual.isDeepEqual)(fetchParams, currentParams)) {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
const cacheResponses = cacheChunkManager.splitResponse(fetchParams, response);
|
|
181
|
+
cacheResponses.forEach((cacheResponse, key) => cache.set(key, cacheResponse));
|
|
182
|
+
apiRef.current.applyStrategyProcessor('dataSourceRowsUpdate', {
|
|
183
|
+
response,
|
|
184
|
+
fetchParams,
|
|
185
|
+
options: {}
|
|
186
|
+
});
|
|
187
|
+
revalidateExpandedGroups();
|
|
188
|
+
} catch {
|
|
189
|
+
// Ignore background revalidation errors.
|
|
190
|
+
}
|
|
191
|
+
});
|
|
192
|
+
const stopPolling = React.useCallback(() => {
|
|
193
|
+
if (pollingIntervalRef.current !== null) {
|
|
194
|
+
clearInterval(pollingIntervalRef.current);
|
|
195
|
+
pollingIntervalRef.current = null;
|
|
196
|
+
}
|
|
197
|
+
}, []);
|
|
198
|
+
const startPolling = (0, _useEventCallback.default)(() => {
|
|
199
|
+
stopPolling();
|
|
200
|
+
if (revalidateMs <= 0 || !standardRowsUpdateStrategyActive) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
pollingIntervalRef.current = setInterval(revalidate, revalidateMs);
|
|
204
|
+
});
|
|
138
205
|
const handleDataUpdate = React.useCallback(params => {
|
|
139
206
|
if ('error' in params) {
|
|
140
207
|
apiRef.current.setRows([]);
|
|
@@ -151,7 +218,8 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
151
218
|
params: params.fetchParams,
|
|
152
219
|
response
|
|
153
220
|
}, true);
|
|
154
|
-
|
|
221
|
+
startPolling();
|
|
222
|
+
}, [apiRef, startPolling]);
|
|
155
223
|
const dataSourceUpdateRow = props.dataSource?.updateRow;
|
|
156
224
|
const handleEditRowOption = options.handleEditRow;
|
|
157
225
|
const editRow = React.useCallback(async params => {
|
|
@@ -191,6 +259,10 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
191
259
|
}
|
|
192
260
|
};
|
|
193
261
|
const debouncedFetchRows = React.useMemo(() => (0, _debounce.default)(fetchRows, 0), [fetchRows]);
|
|
262
|
+
const handleFetchRowsOnParamsChange = React.useCallback(() => {
|
|
263
|
+
stopPolling();
|
|
264
|
+
debouncedFetchRows();
|
|
265
|
+
}, [stopPolling, debouncedFetchRows]);
|
|
194
266
|
const isFirstRender = React.useRef(true);
|
|
195
267
|
React.useEffect(() => {
|
|
196
268
|
if (isFirstRender.current) {
|
|
@@ -203,6 +275,17 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
203
275
|
const newCache = getCache(props.dataSourceCache, options.cacheOptions);
|
|
204
276
|
setCache(prevCache => prevCache !== newCache ? newCache : prevCache);
|
|
205
277
|
}, [props.dataSourceCache, options.cacheOptions]);
|
|
278
|
+
React.useEffect(() => {
|
|
279
|
+
if (!standardRowsUpdateStrategyActive) {
|
|
280
|
+
stopPolling();
|
|
281
|
+
}
|
|
282
|
+
}, [standardRowsUpdateStrategyActive, stopPolling]);
|
|
283
|
+
React.useEffect(() => {
|
|
284
|
+
if (revalidateMs <= 0) {
|
|
285
|
+
stopPolling();
|
|
286
|
+
}
|
|
287
|
+
}, [revalidateMs, stopPolling]);
|
|
288
|
+
React.useEffect(() => stopPolling, [stopPolling]);
|
|
206
289
|
React.useEffect(() => {
|
|
207
290
|
// Return early if the proper strategy isn't set yet
|
|
208
291
|
// Context: https://github.com/mui/mui-x/issues/19650
|
|
@@ -210,6 +293,8 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
210
293
|
return undefined;
|
|
211
294
|
}
|
|
212
295
|
if (props.dataSource) {
|
|
296
|
+
stopPolling();
|
|
297
|
+
apiRef.current.setRows([]);
|
|
213
298
|
apiRef.current.dataSource.cache.clear();
|
|
214
299
|
apiRef.current.dataSource.fetchRows();
|
|
215
300
|
}
|
|
@@ -217,7 +302,7 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
217
302
|
// ignore the current request on unmount
|
|
218
303
|
lastRequestId.current += 1;
|
|
219
304
|
};
|
|
220
|
-
}, [apiRef, props.dataSource, currentStrategy]);
|
|
305
|
+
}, [apiRef, props.dataSource, currentStrategy, stopPolling]);
|
|
221
306
|
return {
|
|
222
307
|
api: {
|
|
223
308
|
public: dataSourceApi
|
|
@@ -229,13 +314,15 @@ const useGridDataSourceBase = (apiRef, props, options = {}) => {
|
|
|
229
314
|
processor: handleDataUpdate
|
|
230
315
|
},
|
|
231
316
|
setStrategyAvailability,
|
|
317
|
+
startPolling,
|
|
318
|
+
stopPolling,
|
|
232
319
|
cacheChunkManager,
|
|
233
320
|
cache,
|
|
234
321
|
events: {
|
|
235
322
|
strategyAvailabilityChange: handleStrategyActivityChange,
|
|
236
|
-
sortModelChange: (0, _utils.runIf)(standardRowsUpdateStrategyActive,
|
|
237
|
-
filterModelChange: (0, _utils.runIf)(standardRowsUpdateStrategyActive,
|
|
238
|
-
paginationModelChange: (0, _utils.runIf)(standardRowsUpdateStrategyActive,
|
|
323
|
+
sortModelChange: (0, _utils.runIf)(standardRowsUpdateStrategyActive, handleFetchRowsOnParamsChange),
|
|
324
|
+
filterModelChange: (0, _utils.runIf)(standardRowsUpdateStrategyActive, handleFetchRowsOnParamsChange),
|
|
325
|
+
paginationModelChange: (0, _utils.runIf)(standardRowsUpdateStrategyActive, handleFetchRowsOnParamsChange)
|
|
239
326
|
}
|
|
240
327
|
};
|
|
241
328
|
};
|
|
@@ -191,12 +191,15 @@ const useGridRowEditing = (apiRef, props) => {
|
|
|
191
191
|
const rowParams = apiRef.current.getRowParams(params.id);
|
|
192
192
|
const newParams = (0, _extends2.default)({}, rowParams, {
|
|
193
193
|
field: params.field,
|
|
194
|
-
reason
|
|
194
|
+
reason,
|
|
195
|
+
// Only pass the pressed key when the row editing is controlled via `rowModesModel`.
|
|
196
|
+
// In uncontrolled mode, the default editor already inserts the character and passing it here would duplicate it.
|
|
197
|
+
key: rowModesModelProp && (0, _keyboardUtils.isPrintableKey)(event) ? event.key : undefined
|
|
195
198
|
});
|
|
196
199
|
apiRef.current.publishEvent('rowEditStart', newParams, event);
|
|
197
200
|
}
|
|
198
201
|
}
|
|
199
|
-
}, [apiRef, hasFieldsWithErrors]);
|
|
202
|
+
}, [apiRef, hasFieldsWithErrors, rowModesModelProp]);
|
|
200
203
|
const handleRowEditStart = React.useCallback(params => {
|
|
201
204
|
const {
|
|
202
205
|
id,
|
|
@@ -208,10 +211,17 @@ const useGridRowEditing = (apiRef, props) => {
|
|
|
208
211
|
fieldToFocus: field
|
|
209
212
|
};
|
|
210
213
|
if (reason === _gridRowParams.GridRowEditStartReasons.printableKeyDown || reason === _gridRowParams.GridRowEditStartReasons.deleteKeyDown) {
|
|
211
|
-
|
|
214
|
+
// If the user typed a printable key, initialize the value with that key
|
|
215
|
+
// to avoid losing the first character when the component is controlled.
|
|
216
|
+
if (rowModesModelProp && reason === _gridRowParams.GridRowEditStartReasons.printableKeyDown && params.key && field) {
|
|
217
|
+
startRowEditModeParams.initialValue = params.key;
|
|
218
|
+
} else {
|
|
219
|
+
// For Delete / Backspace or for uncontrolled row editing we clear the value
|
|
220
|
+
startRowEditModeParams.deleteValue = !!field;
|
|
221
|
+
}
|
|
212
222
|
}
|
|
213
223
|
apiRef.current.startRowEditMode(startRowEditModeParams);
|
|
214
|
-
}, [apiRef]);
|
|
224
|
+
}, [apiRef, rowModesModelProp]);
|
|
215
225
|
const handleRowEditStop = React.useCallback(params => {
|
|
216
226
|
const {
|
|
217
227
|
id,
|
package/index.js
CHANGED
|
@@ -73,7 +73,6 @@ export interface GridRowEditStartParams<R extends GridValidRowModel = any> exten
|
|
|
73
73
|
reason?: GridRowEditStartReasons;
|
|
74
74
|
/**
|
|
75
75
|
* If the reason is related to a keyboard event, it contains which key was pressed.
|
|
76
|
-
* @deprecated No longer needed.
|
|
77
76
|
*/
|
|
78
77
|
key?: string;
|
|
79
78
|
}
|
|
@@ -325,6 +325,13 @@ export interface DataGridPropsWithDefaultValues<R extends GridValidRowModel = an
|
|
|
325
325
|
* @default 0
|
|
326
326
|
*/
|
|
327
327
|
throttleRowsMs: number;
|
|
328
|
+
/**
|
|
329
|
+
* If positive, the Data Grid will periodically revalidate data source rows by re-fetching them from the server when the cache entry has expired.
|
|
330
|
+
* If the refetched rows are different from the current rows, the grid will update the rows.
|
|
331
|
+
* Set to `0` to disable polling.
|
|
332
|
+
* @default 0
|
|
333
|
+
*/
|
|
334
|
+
dataSourceRevalidateMs: number;
|
|
328
335
|
/**
|
|
329
336
|
* If `true`, reordering columns is disabled.
|
|
330
337
|
* @default false
|