slickgrid-react 5.13.0 → 5.13.2
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/README.md +18 -11
- package/dist/cjs/extensions/slickRowDetailView.js +66 -67
- package/dist/cjs/extensions/slickRowDetailView.js.map +1 -1
- package/dist/esm/extensions/slickRowDetailView.js +67 -68
- package/dist/esm/extensions/slickRowDetailView.js.map +1 -1
- package/dist/types/extensions/slickRowDetailView.d.ts +9 -11
- package/dist/types/extensions/slickRowDetailView.d.ts.map +1 -1
- package/dist/types/models/gridOption.interface.d.ts +2 -1
- package/dist/types/models/gridOption.interface.d.ts.map +1 -1
- package/package.json +30 -30
- package/src/slickgrid-react/extensions/slickRowDetailView.ts +71 -71
- package/src/slickgrid-react/models/gridOption.interface.ts +2 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
addToArrayWhenNotExists,
|
|
3
|
+
createDomElement,
|
|
3
4
|
type EventSubscription,
|
|
4
5
|
type OnBeforeRowDetailToggleArgs,
|
|
5
6
|
type OnRowBackToViewportRangeArgs,
|
|
6
7
|
SlickEventData,
|
|
7
|
-
type SlickEventHandler,
|
|
8
8
|
type SlickGrid,
|
|
9
9
|
SlickRowSelectionModel,
|
|
10
10
|
unsubscribeAll,
|
|
@@ -51,13 +51,6 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
51
51
|
return this.gridOptions.datasetIdPropertyName || 'id';
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
get eventHandler(): SlickEventHandler {
|
|
55
|
-
return this._eventHandler;
|
|
56
|
-
}
|
|
57
|
-
set eventHandler(eventHandler: SlickEventHandler) {
|
|
58
|
-
this._eventHandler = eventHandler;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
54
|
get gridOptions(): GridOption {
|
|
62
55
|
return (this._grid?.getOptions() || {}) as GridOption;
|
|
63
56
|
}
|
|
@@ -78,7 +71,7 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
78
71
|
do {
|
|
79
72
|
const view = this._views.pop();
|
|
80
73
|
if (view) {
|
|
81
|
-
this.
|
|
74
|
+
this.disposeViewByItem(view);
|
|
82
75
|
}
|
|
83
76
|
} while (this._views.length > 0);
|
|
84
77
|
}
|
|
@@ -114,11 +107,12 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
114
107
|
// when those are React Components, we need to create View Component & provide the html containers to the Plugin (preTemplate/postTemplate methods)
|
|
115
108
|
if (!this.gridOptions.rowDetailView.preTemplate) {
|
|
116
109
|
this._preloadComponent = this.gridOptions?.rowDetailView?.preloadComponent;
|
|
117
|
-
this.addonOptions.preTemplate = () =>
|
|
110
|
+
this.addonOptions.preTemplate = () => createDomElement('div', { className: `${PRELOAD_CONTAINER_PREFIX}` });
|
|
118
111
|
}
|
|
119
112
|
if (!this.gridOptions.rowDetailView.postTemplate) {
|
|
120
113
|
this._component = this.gridOptions?.rowDetailView?.viewComponent;
|
|
121
|
-
this.addonOptions.postTemplate = (itemDetail: any) =>
|
|
114
|
+
this.addonOptions.postTemplate = (itemDetail: any) =>
|
|
115
|
+
createDomElement('div', { className: `${ROW_DETAIL_CONTAINER_PREFIX}${itemDetail[this.datasetIdPropName]}` });
|
|
122
116
|
}
|
|
123
117
|
|
|
124
118
|
if (this._grid && this.gridOptions) {
|
|
@@ -145,7 +139,7 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
145
139
|
this._preloadRoot?.unmount();
|
|
146
140
|
|
|
147
141
|
// triggers after backend called "onAsyncResponse.notify()"
|
|
148
|
-
|
|
142
|
+
this.renderViewModel(args?.item);
|
|
149
143
|
|
|
150
144
|
if (typeof this.rowDetailViewOptions?.onAsyncEndUpdate === 'function') {
|
|
151
145
|
this.rowDetailViewOptions.onAsyncEndUpdate(event, args);
|
|
@@ -155,7 +149,7 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
155
149
|
this._eventHandler.subscribe(this.onAfterRowDetailToggle, async (event, args) => {
|
|
156
150
|
// display preload template & re-render all the other Detail Views after toggling
|
|
157
151
|
// the preload View will eventually go away once the data gets loaded after the "onAsyncEndUpdate" event
|
|
158
|
-
|
|
152
|
+
this.renderPreloadView(args.item);
|
|
159
153
|
|
|
160
154
|
if (typeof this.rowDetailViewOptions?.onAfterRowDetailToggle === 'function') {
|
|
161
155
|
this.rowDetailViewOptions.onAfterRowDetailToggle(event, args);
|
|
@@ -174,7 +168,7 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
174
168
|
|
|
175
169
|
this._eventHandler.subscribe(this.onRowBackToViewportRange, async (event, args) => {
|
|
176
170
|
// when row is back to viewport range, we will re-render the View Component(s)
|
|
177
|
-
|
|
171
|
+
this.handleOnRowBackToViewportRange(event, args);
|
|
178
172
|
|
|
179
173
|
if (typeof this.rowDetailViewOptions?.onRowBackToViewportRange === 'function') {
|
|
180
174
|
this.rowDetailViewOptions.onRowBackToViewportRange(event, args);
|
|
@@ -185,7 +179,7 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
185
179
|
if (typeof this.rowDetailViewOptions?.onBeforeRowOutOfViewportRange === 'function') {
|
|
186
180
|
this.rowDetailViewOptions.onBeforeRowOutOfViewportRange(event, args);
|
|
187
181
|
}
|
|
188
|
-
this.
|
|
182
|
+
this.disposeViewByItem(args.item);
|
|
189
183
|
});
|
|
190
184
|
|
|
191
185
|
this._eventHandler.subscribe(this.onRowOutOfViewportRange, (event, args) => {
|
|
@@ -198,11 +192,11 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
198
192
|
// hook some events needed by the Plugin itself
|
|
199
193
|
|
|
200
194
|
// we need to redraw the open detail views if we change column position (column reorder)
|
|
201
|
-
this.eventHandler.subscribe(this._grid.onColumnsReordered, this.redrawAllViewComponents
|
|
195
|
+
this.eventHandler.subscribe(this._grid.onColumnsReordered, () => this.redrawAllViewComponents(false));
|
|
202
196
|
|
|
203
197
|
// on row selection changed, we also need to redraw
|
|
204
198
|
if (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector) {
|
|
205
|
-
this._eventHandler.subscribe(this._grid.onSelectedRowsChanged, this.redrawAllViewComponents
|
|
199
|
+
this._eventHandler.subscribe(this._grid.onSelectedRowsChanged, () => this.redrawAllViewComponents(false));
|
|
206
200
|
}
|
|
207
201
|
|
|
208
202
|
// on column sort/reorder, all row detail are collapsed so we can dispose of all the Views as well
|
|
@@ -210,8 +204,15 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
210
204
|
|
|
211
205
|
// on filter changed, we need to re-render all Views
|
|
212
206
|
this._subscriptions.push(
|
|
213
|
-
this.eventPubSubService?.subscribe([
|
|
214
|
-
|
|
207
|
+
this.eventPubSubService?.subscribe([
|
|
208
|
+
'onFilterChanged',
|
|
209
|
+
'onGridMenuColumnsChanged',
|
|
210
|
+
'onColumnPickerColumnsChanged',
|
|
211
|
+
'onGridMenuClearAllFilters',
|
|
212
|
+
'onGridMenuClearAllSorting'
|
|
213
|
+
],
|
|
214
|
+
() => this.redrawAllViewComponents(true)
|
|
215
|
+
),
|
|
215
216
|
);
|
|
216
217
|
}
|
|
217
218
|
}
|
|
@@ -221,38 +222,37 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
221
222
|
}
|
|
222
223
|
|
|
223
224
|
/** Redraw (re-render) all the expanded row detail View Components */
|
|
224
|
-
async redrawAllViewComponents() {
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
225
|
+
async redrawAllViewComponents(forceRedraw = false) {
|
|
226
|
+
setTimeout(() => {
|
|
227
|
+
this.resetRenderedRows();
|
|
228
|
+
this._views.forEach((view) => {
|
|
229
|
+
if (!view.rendered || forceRedraw) {
|
|
230
|
+
forceRedraw && this.disposeViewComponent(view);
|
|
231
|
+
this.redrawViewComponent(view)
|
|
232
|
+
}
|
|
233
|
+
});
|
|
231
234
|
});
|
|
232
|
-
await Promise.all(promises);
|
|
233
235
|
}
|
|
234
236
|
|
|
235
237
|
/** Render all the expanded row detail View Components */
|
|
236
238
|
async renderAllViewModels() {
|
|
237
|
-
|
|
238
|
-
Array.from(this._views)
|
|
239
|
+
this._views
|
|
239
240
|
.filter((x) => x?.dataContext)
|
|
240
|
-
.forEach((x) =>
|
|
241
|
-
await Promise.all(promises);
|
|
241
|
+
.forEach((x) => this.renderViewModel(x.dataContext));
|
|
242
242
|
}
|
|
243
243
|
|
|
244
244
|
/** Redraw the necessary View Component */
|
|
245
|
-
|
|
246
|
-
const
|
|
247
|
-
if (
|
|
248
|
-
|
|
245
|
+
redrawViewComponent(view: CreatedView) {
|
|
246
|
+
const containerElement = this.gridContainerElement.querySelector(`.${ROW_DETAIL_CONTAINER_PREFIX}${view.id}`);
|
|
247
|
+
if (containerElement) {
|
|
248
|
+
this.renderViewModel(view.dataContext);
|
|
249
249
|
}
|
|
250
250
|
}
|
|
251
251
|
|
|
252
252
|
/** Render (or re-render) the View Component (Row Detail) */
|
|
253
|
-
|
|
254
|
-
const
|
|
255
|
-
if (this._preloadComponent &&
|
|
253
|
+
renderPreloadView(item: any) {
|
|
254
|
+
const containerElement = this.gridContainerElement.querySelector(`.${PRELOAD_CONTAINER_PREFIX}`);
|
|
255
|
+
if (this._preloadComponent && containerElement) {
|
|
256
256
|
// render row detail
|
|
257
257
|
const bindableData = {
|
|
258
258
|
model: item,
|
|
@@ -262,18 +262,17 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
262
262
|
parent: this.rowDetailViewOptions?.parent,
|
|
263
263
|
} as ViewModelBindableInputData;
|
|
264
264
|
const detailContainer = document.createElement('section');
|
|
265
|
-
|
|
265
|
+
containerElement.appendChild(detailContainer);
|
|
266
266
|
|
|
267
|
-
const { root } =
|
|
267
|
+
const { root } = createReactComponentDynamically(this._preloadComponent, detailContainer, bindableData);
|
|
268
268
|
this._preloadRoot = root;
|
|
269
269
|
}
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
/** Render (or re-render) the View Component (Row Detail) */
|
|
273
|
-
|
|
274
|
-
const
|
|
275
|
-
if (this._component &&
|
|
276
|
-
// render row detail
|
|
273
|
+
renderViewModel(item: any) {
|
|
274
|
+
const containerElement = this.gridContainerElement.querySelector<HTMLElement>(`.${ROW_DETAIL_CONTAINER_PREFIX}${item[this.datasetIdPropName]}`);
|
|
275
|
+
if (this._component && containerElement) {
|
|
277
276
|
const bindableData = {
|
|
278
277
|
model: item,
|
|
279
278
|
addon: this,
|
|
@@ -281,24 +280,17 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
281
280
|
dataView: this.dataView,
|
|
282
281
|
parent: this.rowDetailViewOptions?.parent,
|
|
283
282
|
} as ViewModelBindableInputData;
|
|
284
|
-
const viewObj = this._views.find(obj => obj.id === item[this.datasetIdPropName]);
|
|
285
|
-
|
|
286
|
-
// remove any previous mounted views, if found then unmount them and delete them from our references array
|
|
287
|
-
// const viewIdx = this._views.findIndex((obj) => obj.id === item[this.datasetIdPropName]);
|
|
288
|
-
// if (this._views[viewIdx]?.root) {
|
|
289
|
-
// this._views[viewIdx].root.unmount();
|
|
290
|
-
// this._views.splice(viewIdx, 1);
|
|
291
|
-
// }
|
|
292
283
|
|
|
293
284
|
// load our Row Detail React Component dynamically, typically we would want to use `root.render()` after the preload component (last argument below)
|
|
294
285
|
// BUT the root render doesn't seem to work and shows a blank element, so we'll use `createRoot()` every time even though it shows a console log in Dev
|
|
295
286
|
// that is the only way I got it working so let's use it anyway and console warnings are removed in production anyway
|
|
296
|
-
const
|
|
287
|
+
const viewObj = this._views.find(obj => obj.id === item[this.datasetIdPropName]);
|
|
288
|
+
const { root } = createReactComponentDynamically(this._component, containerElement, bindableData);
|
|
297
289
|
if (viewObj) {
|
|
298
290
|
viewObj.root = root;
|
|
299
291
|
viewObj.rendered = true;
|
|
300
292
|
} else {
|
|
301
|
-
this.
|
|
293
|
+
this.upsertViewRefs(item, root);
|
|
302
294
|
}
|
|
303
295
|
}
|
|
304
296
|
}
|
|
@@ -307,19 +299,26 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
307
299
|
// protected functions
|
|
308
300
|
// ------------------
|
|
309
301
|
|
|
310
|
-
protected
|
|
302
|
+
protected upsertViewRefs(item: any, root: Root | null) {
|
|
303
|
+
const viewIdx = this._views.findIndex(obj => obj.id === item[this.datasetIdPropName]);
|
|
311
304
|
const viewInfo: CreatedView = {
|
|
312
305
|
id: item[this.datasetIdPropName],
|
|
313
306
|
dataContext: item,
|
|
314
307
|
root,
|
|
315
308
|
rendered: !!root,
|
|
316
309
|
};
|
|
310
|
+
if (viewIdx >= 0) {
|
|
311
|
+
this._views[viewIdx] = viewInfo;
|
|
312
|
+
} else {
|
|
313
|
+
this._views.push(viewInfo);
|
|
314
|
+
}
|
|
317
315
|
addToArrayWhenNotExists(this._views, viewInfo, this.datasetIdPropName);
|
|
318
316
|
}
|
|
319
317
|
|
|
320
|
-
protected
|
|
318
|
+
protected disposeViewByItem(item: any, removeFromArray = false): void {
|
|
321
319
|
const foundViewIdx = this._views.findIndex((view: CreatedView) => view.id === item[this.datasetIdPropName]);
|
|
322
|
-
if (foundViewIdx >= 0
|
|
320
|
+
if (foundViewIdx >= 0) {
|
|
321
|
+
this.disposeViewComponent(this._views[foundViewIdx]);
|
|
323
322
|
if (removeFromArray) {
|
|
324
323
|
this._views.splice(foundViewIdx, 1);
|
|
325
324
|
}
|
|
@@ -327,11 +326,12 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
327
326
|
}
|
|
328
327
|
|
|
329
328
|
protected disposeViewComponent(expandedView: CreatedView): CreatedView | void {
|
|
329
|
+
expandedView.rendered = false;
|
|
330
330
|
if (expandedView?.root) {
|
|
331
|
-
const container = this.gridContainerElement.
|
|
332
|
-
if (container
|
|
331
|
+
const container = this.gridContainerElement.querySelector(`.${ROW_DETAIL_CONTAINER_PREFIX}${expandedView.id}`);
|
|
332
|
+
if (container) {
|
|
333
333
|
expandedView.root.unmount();
|
|
334
|
-
container
|
|
334
|
+
container.textContent = '';
|
|
335
335
|
return expandedView;
|
|
336
336
|
}
|
|
337
337
|
}
|
|
@@ -340,17 +340,17 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
340
340
|
/**
|
|
341
341
|
* Just before the row get expanded or collapsed we will do the following
|
|
342
342
|
* First determine if the row is expanding or collapsing,
|
|
343
|
-
* if it's expanding we will add it to our View Components reference array
|
|
344
|
-
* or if it's collapsing we will remove it from our View Components reference array
|
|
343
|
+
* if it's expanding we will add it to our View Components reference array,
|
|
344
|
+
* if we don't already have it or if it's collapsing we will remove it from our View Components reference array
|
|
345
345
|
*/
|
|
346
346
|
protected handleOnBeforeRowDetailToggle(_e: SlickEventData<OnBeforeRowDetailToggleArgs>, args: { grid: SlickGrid; item: any; }) {
|
|
347
347
|
// expanding
|
|
348
348
|
if (args?.item?.__collapsed) {
|
|
349
349
|
// expanding row detail
|
|
350
|
-
this.
|
|
350
|
+
this.upsertViewRefs(args.item, null);
|
|
351
351
|
} else {
|
|
352
352
|
// collapsing, so dispose of the View
|
|
353
|
-
this.
|
|
353
|
+
this.disposeViewByItem(args.item, true);
|
|
354
354
|
}
|
|
355
355
|
}
|
|
356
356
|
|
|
@@ -363,8 +363,8 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
363
363
|
rowIdsOutOfViewport: (string | number)[];
|
|
364
364
|
grid: SlickGrid;
|
|
365
365
|
}) {
|
|
366
|
-
const viewModel =
|
|
367
|
-
if (viewModel) {
|
|
366
|
+
const viewModel = this._views.find((x) => x.id === args.rowId);
|
|
367
|
+
if (viewModel && !viewModel.rendered) {
|
|
368
368
|
this.redrawViewComponent(viewModel);
|
|
369
369
|
}
|
|
370
370
|
}
|
|
@@ -375,9 +375,7 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
375
375
|
* @param item
|
|
376
376
|
*/
|
|
377
377
|
protected notifyTemplate(item: any) {
|
|
378
|
-
|
|
379
|
-
this.onAsyncResponse.notify({ item, itemDetail: item }, new SlickEventData(), this);
|
|
380
|
-
}
|
|
378
|
+
this.onAsyncResponse.notify({ item, itemDetail: item }, new SlickEventData(), this);
|
|
381
379
|
}
|
|
382
380
|
|
|
383
381
|
/**
|
|
@@ -401,8 +399,10 @@ export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
|
401
399
|
}
|
|
402
400
|
|
|
403
401
|
if (!awaitedItemDetail || !awaitedItemDetail.hasOwnProperty(this.datasetIdPropName)) {
|
|
404
|
-
throw new Error(
|
|
405
|
-
'
|
|
402
|
+
throw new Error(
|
|
403
|
+
'[Slickgrid-React] could not process the Row Detail, please make sure that your "process" callback ' +
|
|
404
|
+
`returns an item object that has an "${this.datasetIdPropName}" property`
|
|
405
|
+
);
|
|
406
406
|
}
|
|
407
407
|
|
|
408
408
|
// notify the plugin with the new item details
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import type { BasePaginationComponent, BasePaginationModel, GridOption as UniversalGridOption } from '@slickgrid-universal/common';
|
|
2
2
|
import type * as i18next from 'i18next';
|
|
3
|
+
import type { ForwardRefExoticComponent, RefAttributes } from 'react';
|
|
3
4
|
|
|
4
5
|
import type { RowDetailView } from './rowDetailView.interface';
|
|
5
6
|
|
|
6
7
|
export interface GridOption extends UniversalGridOption {
|
|
7
8
|
/** External Custom Pagination Component that can be provided by the user */
|
|
8
|
-
customPaginationComponent?: typeof BasePaginationComponent | (() => BasePaginationModel)
|
|
9
|
+
customPaginationComponent?: typeof BasePaginationComponent | (() => BasePaginationModel) | ForwardRefExoticComponent<any & RefAttributes<any>>;
|
|
9
10
|
|
|
10
11
|
/** I18N translation service instance */
|
|
11
12
|
i18n?: i18next.i18n;
|