slickgrid-react 5.8.0 → 5.9.0
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 +8 -0
- package/dist/cjs/components/slickgrid-react.js +44 -32
- package/dist/cjs/components/slickgrid-react.js.map +1 -1
- package/dist/cjs/extensions/slickRowDetailView.js +316 -0
- package/dist/cjs/extensions/slickRowDetailView.js.map +1 -0
- package/dist/cjs/global-grid-options.js +9 -0
- package/dist/cjs/global-grid-options.js.map +1 -1
- package/dist/cjs/index.js +3 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/models/rowDetailView.interface.js +3 -0
- package/dist/cjs/models/rowDetailView.interface.js.map +1 -0
- package/dist/cjs/models/viewModelBindableData.interface.js +3 -0
- package/dist/cjs/models/viewModelBindableData.interface.js.map +1 -0
- package/dist/cjs/models/viewModelBindableInputData.interface.js +3 -0
- package/dist/cjs/models/viewModelBindableInputData.interface.js.map +1 -0
- package/dist/cjs/services/index.js +0 -1
- package/dist/cjs/services/index.js.map +1 -1
- package/dist/cjs/services/reactUtils.js +20 -0
- package/dist/cjs/services/reactUtils.js.map +1 -0
- package/dist/esm/components/slickgrid-react.js +43 -31
- package/dist/esm/components/slickgrid-react.js.map +1 -1
- package/dist/esm/extensions/slickRowDetailView.js +312 -0
- package/dist/esm/extensions/slickRowDetailView.js.map +1 -0
- package/dist/esm/global-grid-options.js +9 -0
- package/dist/esm/global-grid-options.js.map +1 -1
- package/dist/esm/index.js +3 -2
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/models/rowDetailView.interface.js +2 -0
- package/dist/esm/models/rowDetailView.interface.js.map +1 -0
- package/dist/esm/models/viewModelBindableData.interface.js +2 -0
- package/dist/esm/models/viewModelBindableData.interface.js.map +1 -0
- package/dist/esm/models/viewModelBindableInputData.interface.js +2 -0
- package/dist/esm/models/viewModelBindableInputData.interface.js.map +1 -0
- package/dist/esm/services/index.js +0 -1
- package/dist/esm/services/index.js.map +1 -1
- package/dist/esm/services/reactUtils.js +14 -0
- package/dist/esm/services/reactUtils.js.map +1 -0
- package/dist/types/components/slickgrid-react.d.ts +13 -14
- package/dist/types/components/slickgrid-react.d.ts.map +1 -1
- package/dist/types/components/slickgridReactProps.d.ts +0 -2
- package/dist/types/components/slickgridReactProps.d.ts.map +1 -1
- package/dist/types/extensions/slickRowDetailView.d.ts +82 -0
- package/dist/types/extensions/slickRowDetailView.d.ts.map +1 -0
- package/dist/types/global-grid-options.d.ts.map +1 -1
- package/dist/types/index.d.ts +4 -3
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/models/gridOption.interface.d.ts +3 -0
- package/dist/types/models/gridOption.interface.d.ts.map +1 -1
- package/dist/types/models/index.d.ts +5 -2
- package/dist/types/models/index.d.ts.map +1 -1
- package/dist/types/models/rowDetailView.interface.d.ts +13 -0
- package/dist/types/models/rowDetailView.interface.d.ts.map +1 -0
- package/dist/types/models/slickgridReactInstance.interface.d.ts +4 -2
- package/dist/types/models/slickgridReactInstance.interface.d.ts.map +1 -1
- package/dist/types/models/viewModelBindableData.interface.d.ts +10 -0
- package/dist/types/models/viewModelBindableData.interface.d.ts.map +1 -0
- package/dist/types/models/viewModelBindableInputData.interface.d.ts +9 -0
- package/dist/types/models/viewModelBindableInputData.interface.d.ts.map +1 -0
- package/dist/types/services/index.d.ts +0 -1
- package/dist/types/services/index.d.ts.map +1 -1
- package/dist/types/services/reactUtils.d.ts +6 -0
- package/dist/types/services/reactUtils.d.ts.map +1 -0
- package/package.json +48 -69
- package/src/slickgrid-react/components/slickgrid-react.tsx +53 -44
- package/src/slickgrid-react/components/slickgridReactProps.ts +0 -2
- package/src/slickgrid-react/extensions/slickRowDetailView.ts +383 -0
- package/src/slickgrid-react/global-grid-options.ts +10 -1
- package/src/slickgrid-react/index.ts +5 -2
- package/src/slickgrid-react/models/gridOption.interface.ts +5 -0
- package/src/slickgrid-react/models/index.ts +5 -2
- package/src/slickgrid-react/models/rowDetailView.interface.ts +15 -0
- package/src/slickgrid-react/models/slickgridReactInstance.interface.ts +5 -2
- package/src/slickgrid-react/models/viewModelBindableData.interface.ts +10 -0
- package/src/slickgrid-react/models/viewModelBindableInputData.interface.ts +9 -0
- package/src/slickgrid-react/services/index.ts +0 -1
- package/src/slickgrid-react/services/reactUtils.ts +15 -0
- package/dist/cjs/services/reactUtil.service.js +0 -30
- package/dist/cjs/services/reactUtil.service.js.map +0 -1
- package/dist/esm/services/reactUtil.service.js +0 -23
- package/dist/esm/services/reactUtil.service.js.map +0 -1
- package/dist/types/services/reactUtil.service.d.ts +0 -6
- package/dist/types/services/reactUtil.service.d.ts.map +0 -1
- package/src/slickgrid-react/services/reactUtil.service.ts +0 -26
|
@@ -1,13 +1,10 @@
|
|
|
1
|
-
// import 3rd party vendor libs
|
|
2
|
-
import i18next from 'i18next';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
|
|
5
1
|
import {
|
|
6
2
|
// interfaces/types
|
|
7
3
|
type AutocompleterEditor,
|
|
8
4
|
type BackendService,
|
|
9
5
|
type BackendServiceApi,
|
|
10
6
|
type BackendServiceOption,
|
|
7
|
+
type BasePaginationComponent,
|
|
11
8
|
type Column,
|
|
12
9
|
type DataViewOption,
|
|
13
10
|
type EventSubscription,
|
|
@@ -18,8 +15,8 @@ import {
|
|
|
18
15
|
type Locale,
|
|
19
16
|
type Metrics,
|
|
20
17
|
type Pagination,
|
|
18
|
+
type PaginationMetadata,
|
|
21
19
|
type SelectEditor,
|
|
22
|
-
type ServicePagination,
|
|
23
20
|
SlickDataView,
|
|
24
21
|
SlickEventHandler,
|
|
25
22
|
SlickGrid,
|
|
@@ -35,7 +32,7 @@ import {
|
|
|
35
32
|
GridEventService,
|
|
36
33
|
GridService,
|
|
37
34
|
GridStateService,
|
|
38
|
-
|
|
35
|
+
HeaderGroupingService,
|
|
39
36
|
type Observable,
|
|
40
37
|
PaginationService,
|
|
41
38
|
ResizerService,
|
|
@@ -56,22 +53,21 @@ import { SlickFooterComponent } from '@slickgrid-universal/custom-footer-compone
|
|
|
56
53
|
import { SlickEmptyWarningComponent } from '@slickgrid-universal/empty-warning-component';
|
|
57
54
|
import { SlickPaginationComponent } from '@slickgrid-universal/pagination-component';
|
|
58
55
|
import { extend } from '@slickgrid-universal/utils';
|
|
59
|
-
|
|
60
56
|
import { dequal } from 'dequal/lite';
|
|
57
|
+
import i18next from 'i18next';
|
|
58
|
+
import React from 'react';
|
|
59
|
+
import type { Subscription } from 'rxjs';
|
|
60
|
+
|
|
61
61
|
import { Constants } from '../constants';
|
|
62
62
|
import { GlobalGridOptions } from '../global-grid-options';
|
|
63
63
|
import type { SlickgridReactInstance, GridOption, } from '../models/index';
|
|
64
|
-
import {
|
|
65
|
-
ReactUtilService,
|
|
66
|
-
disposeAllSubscriptions,
|
|
67
|
-
TranslaterService,
|
|
68
|
-
} from '../services/index';
|
|
69
|
-
import type { Subscription } from 'rxjs';
|
|
70
|
-
|
|
64
|
+
import { disposeAllSubscriptions } from '../services/utilities';
|
|
71
65
|
import { GlobalContainerService } from '../services/singletons';
|
|
66
|
+
import { loadReactComponentDynamically } from '../services/reactUtils';
|
|
67
|
+
import { TranslaterService } from '../services/translater.service';
|
|
72
68
|
import type { SlickgridReactProps } from './slickgridReactProps';
|
|
73
69
|
|
|
74
|
-
const WARN_NO_PREPARSE_DATE_SIZE =
|
|
70
|
+
const WARN_NO_PREPARSE_DATE_SIZE = 10000; // data size to warn user when pre-parse isn't enabled
|
|
75
71
|
|
|
76
72
|
interface State {
|
|
77
73
|
showPagination: boolean;
|
|
@@ -153,7 +149,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
153
149
|
// components
|
|
154
150
|
slickEmptyWarning: SlickEmptyWarningComponent | undefined;
|
|
155
151
|
slickFooter: SlickFooterComponent | undefined;
|
|
156
|
-
slickPagination:
|
|
152
|
+
slickPagination: BasePaginationComponent | undefined;
|
|
157
153
|
|
|
158
154
|
// services
|
|
159
155
|
backendUtilityService!: BackendUtilityService;
|
|
@@ -165,13 +161,8 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
165
161
|
gridEventService: GridEventService;
|
|
166
162
|
gridService: GridService;
|
|
167
163
|
gridStateService: GridStateService;
|
|
168
|
-
groupingService
|
|
169
|
-
|
|
170
|
-
return this.state?.paginationService;
|
|
171
|
-
}
|
|
172
|
-
protected set paginationService(value: PaginationService) {
|
|
173
|
-
this.setStateValue('paginationService', value);
|
|
174
|
-
}
|
|
164
|
+
groupingService!: HeaderGroupingService;
|
|
165
|
+
headerGroupingService: HeaderGroupingService;
|
|
175
166
|
resizerService!: ResizerService;
|
|
176
167
|
rxjs?: RxJsFacade;
|
|
177
168
|
sharedService: SharedService;
|
|
@@ -186,7 +177,6 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
186
177
|
instances: SlickgridReactInstance | null = null;
|
|
187
178
|
|
|
188
179
|
static defaultProps = {
|
|
189
|
-
reactUtilService: new ReactUtilService(),
|
|
190
180
|
containerService: GlobalContainerService,
|
|
191
181
|
translaterService: new TranslaterService(),
|
|
192
182
|
dataset: [],
|
|
@@ -251,6 +241,13 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
251
241
|
this._isDatasetHierarchicalInitialized = true;
|
|
252
242
|
}
|
|
253
243
|
|
|
244
|
+
protected get paginationService(): PaginationService {
|
|
245
|
+
return this.state?.paginationService;
|
|
246
|
+
}
|
|
247
|
+
protected set paginationService(value: PaginationService) {
|
|
248
|
+
this.setStateValue('paginationService', value);
|
|
249
|
+
}
|
|
250
|
+
|
|
254
251
|
constructor(public readonly props: SlickgridReactProps) {
|
|
255
252
|
super(props);
|
|
256
253
|
const slickgridConfig = new SlickgridConfig();
|
|
@@ -293,7 +290,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
293
290
|
|
|
294
291
|
this.gridStateService = new GridStateService(this.extensionService, this.filterService, this._eventPubSubService, this.sharedService, this.sortService, this.treeDataService);
|
|
295
292
|
this.gridService = new GridService(this.gridStateService, this.filterService, this._eventPubSubService, this.paginationService, this.sharedService, this.sortService, this.treeDataService);
|
|
296
|
-
this.
|
|
293
|
+
this.headerGroupingService = new HeaderGroupingService(this.extensionUtility);
|
|
297
294
|
|
|
298
295
|
this.serviceList = [
|
|
299
296
|
this.extensionService,
|
|
@@ -301,7 +298,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
301
298
|
this.gridEventService,
|
|
302
299
|
this.gridService,
|
|
303
300
|
this.gridStateService,
|
|
304
|
-
this.
|
|
301
|
+
this.headerGroupingService,
|
|
305
302
|
this.paginationService,
|
|
306
303
|
this.resizerService,
|
|
307
304
|
this.sortService,
|
|
@@ -322,7 +319,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
322
319
|
this.props.containerService.registerInstance('GridEventService', this.gridEventService);
|
|
323
320
|
this.props.containerService.registerInstance('GridService', this.gridService);
|
|
324
321
|
this.props.containerService.registerInstance('GridStateService', this.gridStateService);
|
|
325
|
-
this.props.containerService.registerInstance('
|
|
322
|
+
this.props.containerService.registerInstance('HeaderGroupingService', this.headerGroupingService);
|
|
326
323
|
this.props.containerService.registerInstance('PaginationService', this.paginationService);
|
|
327
324
|
this.props.containerService.registerInstance('ResizerService', this.resizerService);
|
|
328
325
|
this.props.containerService.registerInstance('SharedService', this.sharedService);
|
|
@@ -591,12 +588,13 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
591
588
|
// return all available Services (non-singleton)
|
|
592
589
|
backendService: this.backendService,
|
|
593
590
|
eventPubSubService: this._eventPubSubService,
|
|
591
|
+
extensionService: this.extensionService,
|
|
594
592
|
filterService: this.filterService,
|
|
595
593
|
gridEventService: this.gridEventService,
|
|
596
594
|
gridStateService: this.gridStateService,
|
|
597
595
|
gridService: this.gridService,
|
|
598
|
-
groupingService: this.
|
|
599
|
-
|
|
596
|
+
groupingService: this.headerGroupingService,
|
|
597
|
+
headerGroupingService: this.headerGroupingService,
|
|
600
598
|
paginationService: this.paginationService,
|
|
601
599
|
resizerService: this.resizerService,
|
|
602
600
|
sortService: this.sortService,
|
|
@@ -765,7 +763,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
765
763
|
if (gridOptions.enableTranslate) {
|
|
766
764
|
this.extensionService.translateAllExtensions(lang);
|
|
767
765
|
if ((gridOptions.createPreHeaderPanel && gridOptions.createTopHeaderPanel) || (gridOptions.createPreHeaderPanel && !gridOptions.enableDraggableGrouping)) {
|
|
768
|
-
this.
|
|
766
|
+
this.headerGroupingService.translateHeaderGrouping();
|
|
769
767
|
}
|
|
770
768
|
}
|
|
771
769
|
});
|
|
@@ -1021,7 +1019,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
1021
1019
|
* On a Pagination changed, we will trigger a Grid State changed with the new pagination info
|
|
1022
1020
|
* Also if we use Row Selection or the Checkbox Selector with a Backend Service (Odata, GraphQL), we need to reset any selection
|
|
1023
1021
|
*/
|
|
1024
|
-
paginationChanged(pagination:
|
|
1022
|
+
paginationChanged(pagination: PaginationMetadata) {
|
|
1025
1023
|
const isSyncGridSelectionEnabled = this.gridStateService?.needToPreserveRowSelection() ?? false;
|
|
1026
1024
|
if (this.grid && !isSyncGridSelectionEnabled && this.gridOptions?.backendServiceApi && (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector)) {
|
|
1027
1025
|
this.grid.setSelectedRows([]);
|
|
@@ -1134,7 +1132,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
1134
1132
|
protected setPaginationOptionsWhenPresetDefined(gridOptions: GridOption, paginationOptions: Pagination): Pagination {
|
|
1135
1133
|
if (gridOptions.presets?.pagination && gridOptions.pagination) {
|
|
1136
1134
|
if (this.hasBackendInfiniteScroll()) {
|
|
1137
|
-
console.warn('[
|
|
1135
|
+
console.warn('[Slickgrid-React] `presets.pagination` is not supported with Infinite Scroll, reverting to first page.');
|
|
1138
1136
|
} else {
|
|
1139
1137
|
paginationOptions.pageSize = gridOptions.presets.pagination.pageSize;
|
|
1140
1138
|
paginationOptions.pageNumber = gridOptions.presets.pagination.pageNumber;
|
|
@@ -1226,8 +1224,8 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
1226
1224
|
this.paginationService.totalItems = this.totalItems;
|
|
1227
1225
|
this.paginationService.init(this.grid, paginationOptions, this.backendServiceApi);
|
|
1228
1226
|
this.subscriptions.push(
|
|
1229
|
-
this._eventPubSubService.subscribe<
|
|
1230
|
-
this._eventPubSubService.subscribe<
|
|
1227
|
+
this._eventPubSubService.subscribe<PaginationMetadata>('onPaginationChanged', paginationChanges => this.paginationChanged(paginationChanges)),
|
|
1228
|
+
this._eventPubSubService.subscribe<PaginationMetadata>('onPaginationOptionsChanged', paginationChanges => this.paginationOptionsChanged(paginationChanges)),
|
|
1231
1229
|
this._eventPubSubService.subscribe<{ visible: boolean; }>('onPaginationVisibilityChanged', (visibility: { visible: boolean }) => {
|
|
1232
1230
|
this.showPagination = visibility?.visible ?? false;
|
|
1233
1231
|
if (this.gridOptions?.backendServiceApi) {
|
|
@@ -1249,11 +1247,22 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
1249
1247
|
* @param {Boolean} showPagination - show (new render) or not (dispose) the Pagination
|
|
1250
1248
|
* @param {Boolean} shouldDisposePaginationService - when disposing the Pagination, do we also want to dispose of the Pagination Service? (defaults to True)
|
|
1251
1249
|
*/
|
|
1252
|
-
protected renderPagination(showPagination = true) {
|
|
1253
|
-
if (this._gridOptions?.enablePagination && !this._isPaginationInitialized && showPagination) {
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1250
|
+
protected async renderPagination(showPagination = true) {
|
|
1251
|
+
if (this.grid && this._gridOptions?.enablePagination && !this._isPaginationInitialized && showPagination) {
|
|
1252
|
+
if (this.gridOptions.customPaginationComponent) {
|
|
1253
|
+
const paginationContainer = document.createElement('section');
|
|
1254
|
+
this._elm!.appendChild(paginationContainer);
|
|
1255
|
+
const { component } = await loadReactComponentDynamically<BasePaginationComponent>(this.gridOptions.customPaginationComponent, paginationContainer);
|
|
1256
|
+
this.slickPagination = component;
|
|
1257
|
+
} else {
|
|
1258
|
+
this.slickPagination = new SlickPaginationComponent();
|
|
1259
|
+
}
|
|
1260
|
+
|
|
1261
|
+
if (this.slickPagination) {
|
|
1262
|
+
this.slickPagination.init(this.grid, this.paginationService, this._eventPubSubService, this.props.translaterService);
|
|
1263
|
+
this.slickPagination.renderPagination(this._elm as HTMLDivElement);
|
|
1264
|
+
this._isPaginationInitialized = true;
|
|
1265
|
+
}
|
|
1257
1266
|
} else if (!showPagination) {
|
|
1258
1267
|
this.slickPagination?.dispose();
|
|
1259
1268
|
this._isPaginationInitialized = false;
|
|
@@ -1268,7 +1277,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
1268
1277
|
|
|
1269
1278
|
if (collectionAsync instanceof Promise) {
|
|
1270
1279
|
// wait for the "collectionAsync", once resolved we will save it into the "collection"
|
|
1271
|
-
// the collectionAsync can be of 3 types
|
|
1280
|
+
// the collectionAsync can be of 3 types Fetch, Promise or RxJS when available
|
|
1272
1281
|
collectionAsync.then((response: any | any[]) => {
|
|
1273
1282
|
if (Array.isArray(response)) {
|
|
1274
1283
|
this.updateEditorCollection(column, response); // from Promise
|
|
@@ -1446,7 +1455,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
1446
1455
|
this._registeredResources = [];
|
|
1447
1456
|
}
|
|
1448
1457
|
|
|
1449
|
-
/** Pre-Register any Resource that don't require SlickGrid to be instantiated (for example RxJS Resource) */
|
|
1458
|
+
/** Pre-Register any Resource that don't require SlickGrid to be instantiated (for example RxJS Resource & RowDetail) */
|
|
1450
1459
|
protected preRegisterResources() {
|
|
1451
1460
|
this._registeredResources = this.gridOptions.externalResources || [];
|
|
1452
1461
|
|
|
@@ -1482,7 +1491,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
1482
1491
|
|
|
1483
1492
|
// when using Grouping/DraggableGrouping/Colspan register its Service
|
|
1484
1493
|
if ((this.gridOptions.createPreHeaderPanel && this.gridOptions.createTopHeaderPanel) || (this.gridOptions.createPreHeaderPanel && !this.gridOptions.enableDraggableGrouping)) {
|
|
1485
|
-
this._registeredResources.push(this.
|
|
1494
|
+
this._registeredResources.push(this.headerGroupingService);
|
|
1486
1495
|
}
|
|
1487
1496
|
|
|
1488
1497
|
// when using Tree Data View, register its Service
|
|
@@ -1564,10 +1573,10 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
|
|
|
1564
1573
|
}
|
|
1565
1574
|
|
|
1566
1575
|
protected suggestDateParsingWhenHelpful() {
|
|
1567
|
-
if (this.dataView?.getItemCount() > WARN_NO_PREPARSE_DATE_SIZE && !this.gridOptions.preParseDateColumns && this.grid.getColumns().some(c => isColumnDateType(c.type))) {
|
|
1576
|
+
if (this.dataView?.getItemCount() > WARN_NO_PREPARSE_DATE_SIZE && !this.gridOptions.silenceWarnings && !this.gridOptions.preParseDateColumns && this.grid.getColumns().some(c => isColumnDateType(c.type))) {
|
|
1568
1577
|
console.warn(
|
|
1569
1578
|
'[Slickgrid-Universal] For getting better perf, we suggest you enable the `preParseDateColumns` grid option, ' +
|
|
1570
|
-
'for more info visit
|
|
1579
|
+
'for more info visit => https://ghiscoding.gitbook.io/slickgrid-react/column-functionalities/sorting#pre-parse-date-columns-for-better-perf'
|
|
1571
1580
|
);
|
|
1572
1581
|
}
|
|
1573
1582
|
}
|
|
@@ -54,12 +54,10 @@ import type {
|
|
|
54
54
|
SlickGrid,
|
|
55
55
|
} from '@slickgrid-universal/common';
|
|
56
56
|
import type { SlickgridReactInstance } from '../models';
|
|
57
|
-
import type { ReactUtilService } from '../services';
|
|
58
57
|
|
|
59
58
|
export interface SlickgridReactProps {
|
|
60
59
|
header?: JSX.Element;
|
|
61
60
|
footer?: JSX.Element;
|
|
62
|
-
reactUtilService: ReactUtilService;
|
|
63
61
|
containerService: ContainerService;
|
|
64
62
|
translaterService: TranslaterService;
|
|
65
63
|
customDataView?: SlickDataView;
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
import {
|
|
2
|
+
addToArrayWhenNotExists,
|
|
3
|
+
type EventSubscription,
|
|
4
|
+
type OnBeforeRowDetailToggleArgs,
|
|
5
|
+
type OnRowBackToViewportRangeArgs,
|
|
6
|
+
SlickEventData,
|
|
7
|
+
type SlickEventHandler,
|
|
8
|
+
type SlickGrid,
|
|
9
|
+
SlickRowSelectionModel,
|
|
10
|
+
unsubscribeAll,
|
|
11
|
+
} from '@slickgrid-universal/common';
|
|
12
|
+
import { type EventPubSubService } from '@slickgrid-universal/event-pub-sub';
|
|
13
|
+
import { SlickRowDetailView as UniversalSlickRowDetailView } from '@slickgrid-universal/row-detail-view-plugin';
|
|
14
|
+
import type { Root } from 'react-dom/client';
|
|
15
|
+
|
|
16
|
+
import type { GridOption, RowDetailView, ViewModelBindableInputData } from '../models/index';
|
|
17
|
+
import { loadReactComponentDynamically } from '../services/reactUtils';
|
|
18
|
+
|
|
19
|
+
const ROW_DETAIL_CONTAINER_PREFIX = 'container_';
|
|
20
|
+
const PRELOAD_CONTAINER_PREFIX = 'container_loading';
|
|
21
|
+
|
|
22
|
+
export interface CreatedView {
|
|
23
|
+
id: string | number;
|
|
24
|
+
dataContext: any;
|
|
25
|
+
root: Root | null;
|
|
26
|
+
}
|
|
27
|
+
// interface SRDV extends React.Component<Props, State>, UniversalSlickRowDetailView {}s
|
|
28
|
+
|
|
29
|
+
export class SlickRowDetailView extends UniversalSlickRowDetailView {
|
|
30
|
+
protected _component?: any;
|
|
31
|
+
protected _preloadComponent?: any;
|
|
32
|
+
protected _views: CreatedView[] = [];
|
|
33
|
+
protected _subscriptions: EventSubscription[] = [];
|
|
34
|
+
protected _userProcessFn?: (item: any) => Promise<any>;
|
|
35
|
+
protected gridContainerElement!: HTMLElement;
|
|
36
|
+
_root?: Root;
|
|
37
|
+
|
|
38
|
+
constructor(
|
|
39
|
+
private readonly eventPubSubService: EventPubSubService,
|
|
40
|
+
) {
|
|
41
|
+
super(eventPubSubService);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
get addonOptions() {
|
|
45
|
+
return this.getOptions();
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
protected get datasetIdPropName(): string {
|
|
49
|
+
return this.gridOptions.datasetIdPropertyName || 'id';
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
get eventHandler(): SlickEventHandler {
|
|
53
|
+
return this._eventHandler;
|
|
54
|
+
}
|
|
55
|
+
set eventHandler(eventHandler: SlickEventHandler) {
|
|
56
|
+
this._eventHandler = eventHandler;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
get gridOptions(): GridOption {
|
|
60
|
+
return (this._grid?.getOptions() || {}) as GridOption;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
get rowDetailViewOptions(): RowDetailView | undefined {
|
|
64
|
+
return this.gridOptions.rowDetailView;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** Dispose of the RowDetailView Extension */
|
|
68
|
+
dispose() {
|
|
69
|
+
this.disposeAllViewComponents();
|
|
70
|
+
unsubscribeAll(this._subscriptions);
|
|
71
|
+
super.dispose();
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** Dispose of all the opened Row Detail Panels Components */
|
|
75
|
+
disposeAllViewComponents() {
|
|
76
|
+
if (Array.isArray(this._views)) {
|
|
77
|
+
this._views.forEach((view) => this.disposeViewComponent(view));
|
|
78
|
+
}
|
|
79
|
+
this._views = [];
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Get the instance of the SlickGrid addon (control or plugin). */
|
|
83
|
+
getAddonInstance(): SlickRowDetailView | null {
|
|
84
|
+
return this;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
init(grid: SlickGrid) {
|
|
88
|
+
this._grid = grid;
|
|
89
|
+
super.init(this._grid);
|
|
90
|
+
this.gridContainerElement = grid.getContainerNode();
|
|
91
|
+
this.register(grid?.getSelectionModel() as SlickRowSelectionModel);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Create the plugin before the Grid creation, else it will behave oddly.
|
|
96
|
+
* Mostly because the column definitions might change after the grid creation
|
|
97
|
+
*/
|
|
98
|
+
register(rowSelectionPlugin?: SlickRowSelectionModel) {
|
|
99
|
+
if (typeof this.gridOptions.rowDetailView?.process === 'function') {
|
|
100
|
+
// we need to keep the user "process" method and replace it with our own execution method
|
|
101
|
+
// we do this because when we get the item detail, we need to call "onAsyncResponse.notify" for the plugin to work
|
|
102
|
+
this._userProcessFn = this.gridOptions.rowDetailView.process as (item: any) => Promise<any>; // keep user's process method
|
|
103
|
+
this.addonOptions.process = (item) => this.onProcessing(item); // replace process method & run our internal one
|
|
104
|
+
} else {
|
|
105
|
+
throw new Error('[Slickgrid-React] You need to provide a "process" function for the Row Detail Extension to work properly');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (this._grid && this.gridOptions?.rowDetailView) {
|
|
109
|
+
// load the Preload & RowDetail Templates (could be straight HTML or React Components)
|
|
110
|
+
// when those are React Components, we need to create View Component & provide the html containers to the Plugin (preTemplate/postTemplate methods)
|
|
111
|
+
if (!this.gridOptions.rowDetailView.preTemplate) {
|
|
112
|
+
this._preloadComponent = this.gridOptions?.rowDetailView?.preloadComponent;
|
|
113
|
+
this.addonOptions.preTemplate = () => this._grid.sanitizeHtmlString(`<div class="${PRELOAD_CONTAINER_PREFIX}"></div>`) as string;
|
|
114
|
+
}
|
|
115
|
+
if (!this.gridOptions.rowDetailView.postTemplate) {
|
|
116
|
+
this._component = this.gridOptions?.rowDetailView?.viewComponent;
|
|
117
|
+
this.addonOptions.postTemplate = (itemDetail: any) => {
|
|
118
|
+
return this._grid.sanitizeHtmlString(`<div class="${ROW_DETAIL_CONTAINER_PREFIX}${itemDetail[this.datasetIdPropName]}"></div>`) as string
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (this._grid && this.gridOptions) {
|
|
123
|
+
// this also requires the Row Selection Model to be registered as well
|
|
124
|
+
if (!rowSelectionPlugin || !this._grid.getSelectionModel()) {
|
|
125
|
+
rowSelectionPlugin = new SlickRowSelectionModel(this.gridOptions.rowSelectionOptions || { selectActiveRow: true });
|
|
126
|
+
this._grid.setSelectionModel(rowSelectionPlugin);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// hook all events
|
|
130
|
+
if (this._grid && this.rowDetailViewOptions) {
|
|
131
|
+
if (this.rowDetailViewOptions.onExtensionRegistered) {
|
|
132
|
+
this.rowDetailViewOptions.onExtensionRegistered(this);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (this.onAsyncResponse) {
|
|
136
|
+
this._eventHandler.subscribe(this.onAsyncResponse, (event, args) => {
|
|
137
|
+
if (typeof this.rowDetailViewOptions?.onAsyncResponse === 'function') {
|
|
138
|
+
this.rowDetailViewOptions.onAsyncResponse(event, args);
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (this.onAsyncEndUpdate) {
|
|
144
|
+
this._eventHandler.subscribe(this.onAsyncEndUpdate, async (event, args) => {
|
|
145
|
+
// triggers after backend called "onAsyncResponse.notify()"
|
|
146
|
+
await this.renderViewModel(args?.item);
|
|
147
|
+
|
|
148
|
+
if (typeof this.rowDetailViewOptions?.onAsyncEndUpdate === 'function') {
|
|
149
|
+
this.rowDetailViewOptions.onAsyncEndUpdate(event, args);
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
if (this.onAfterRowDetailToggle) {
|
|
155
|
+
this._eventHandler.subscribe(this.onAfterRowDetailToggle, async (event, args) => {
|
|
156
|
+
// display preload template & re-render all the other Detail Views after toggling
|
|
157
|
+
// the preload View will eventually go away once the data gets loaded after the "onAsyncEndUpdate" event
|
|
158
|
+
await this.renderPreloadView(args.item);
|
|
159
|
+
this.renderAllViewModels();
|
|
160
|
+
|
|
161
|
+
if (typeof this.rowDetailViewOptions?.onAfterRowDetailToggle === 'function') {
|
|
162
|
+
this.rowDetailViewOptions.onAfterRowDetailToggle(event, args);
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
if (this.onBeforeRowDetailToggle) {
|
|
168
|
+
this._eventHandler.subscribe(this.onBeforeRowDetailToggle, (event, args) => {
|
|
169
|
+
// before toggling row detail, we need to create View Component if it doesn't exist
|
|
170
|
+
this.handleOnBeforeRowDetailToggle(event, args);
|
|
171
|
+
|
|
172
|
+
if (typeof this.rowDetailViewOptions?.onBeforeRowDetailToggle === 'function') {
|
|
173
|
+
return this.rowDetailViewOptions.onBeforeRowDetailToggle(event, args);
|
|
174
|
+
}
|
|
175
|
+
return true;
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
if (this.onRowBackToViewportRange) {
|
|
180
|
+
this._eventHandler.subscribe(this.onRowBackToViewportRange, async (event, args) => {
|
|
181
|
+
// when row is back to viewport range, we will re-render the View Component(s)
|
|
182
|
+
await this.handleOnRowBackToViewportRange(event, args);
|
|
183
|
+
|
|
184
|
+
if (typeof this.rowDetailViewOptions?.onRowBackToViewportRange === 'function') {
|
|
185
|
+
this.rowDetailViewOptions.onRowBackToViewportRange(event, args);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (this.onRowOutOfViewportRange) {
|
|
191
|
+
this._eventHandler.subscribe(this.onRowOutOfViewportRange, (event, args) => {
|
|
192
|
+
if (typeof this.rowDetailViewOptions?.onRowOutOfViewportRange === 'function') {
|
|
193
|
+
this.rowDetailViewOptions.onRowOutOfViewportRange(event, args);
|
|
194
|
+
}
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// --
|
|
199
|
+
// hook some events needed by the Plugin itself
|
|
200
|
+
|
|
201
|
+
// we need to redraw the open detail views if we change column position (column reorder)
|
|
202
|
+
this.eventHandler.subscribe(this._grid.onColumnsReordered, this.redrawAllViewComponents.bind(this));
|
|
203
|
+
|
|
204
|
+
// on row selection changed, we also need to redraw
|
|
205
|
+
if (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector) {
|
|
206
|
+
this._eventHandler.subscribe(this._grid.onSelectedRowsChanged, this.redrawAllViewComponents.bind(this));
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// on column sort/reorder, all row detail are collapsed so we can dispose of all the Views as well
|
|
210
|
+
this._eventHandler.subscribe(this._grid.onSort, this.disposeAllViewComponents.bind(this));
|
|
211
|
+
|
|
212
|
+
// on filter changed, we need to re-render all Views
|
|
213
|
+
this._subscriptions.push(
|
|
214
|
+
this.eventPubSubService?.subscribe(['onFilterChanged', 'onGridMenuColumnsChanged', 'onColumnPickerColumnsChanged'], this.redrawAllViewComponents.bind(this)),
|
|
215
|
+
this.eventPubSubService?.subscribe(['onGridMenuClearAllFilters', 'onGridMenuClearAllSorting'], () => window.setTimeout(() => this.redrawAllViewComponents())),
|
|
216
|
+
);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
return this;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/** Redraw (re-render) all the expanded row detail View Components */
|
|
225
|
+
async redrawAllViewComponents() {
|
|
226
|
+
await Promise.all(this._views.map(async x => this.redrawViewComponent(x)));
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/** Render all the expanded row detail View Components */
|
|
230
|
+
async renderAllViewModels() {
|
|
231
|
+
await Promise.all(this._views.filter(x => x?.dataContext).map(async x => this.renderViewModel(x.dataContext)));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/** Redraw the necessary View Component */
|
|
235
|
+
async redrawViewComponent(view: CreatedView) {
|
|
236
|
+
const containerElement = this.gridContainerElement.getElementsByClassName(`${ROW_DETAIL_CONTAINER_PREFIX}${view.id}`);
|
|
237
|
+
if (containerElement?.length >= 0) {
|
|
238
|
+
await this.renderViewModel(view.dataContext);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/** Render (or re-render) the View Component (Row Detail) */
|
|
243
|
+
async renderPreloadView(item: any) {
|
|
244
|
+
const containerElements = this.gridContainerElement.getElementsByClassName(`${PRELOAD_CONTAINER_PREFIX}`);
|
|
245
|
+
if (this._preloadComponent && containerElements?.length) {
|
|
246
|
+
const detailContainer = document.createElement('section');
|
|
247
|
+
containerElements[containerElements.length - 1]!.appendChild(detailContainer);
|
|
248
|
+
|
|
249
|
+
console.log('elm', containerElements[containerElements.length - 1])
|
|
250
|
+
const { root } = await loadReactComponentDynamically(this._preloadComponent, detailContainer as HTMLElement);
|
|
251
|
+
const viewObj = this._views.find(obj => obj.id === item[this.datasetIdPropName]);
|
|
252
|
+
this._root = root;
|
|
253
|
+
if (viewObj) {
|
|
254
|
+
viewObj.root = root;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
/** Render (or re-render) the View Component (Row Detail) */
|
|
260
|
+
async renderViewModel(item: any) {
|
|
261
|
+
const containerElements = this.gridContainerElement.getElementsByClassName(`${ROW_DETAIL_CONTAINER_PREFIX}${item[this.datasetIdPropName]}`);
|
|
262
|
+
if (this._component && containerElements?.length) {
|
|
263
|
+
const bindableData = {
|
|
264
|
+
model: item,
|
|
265
|
+
addon: this,
|
|
266
|
+
grid: this._grid,
|
|
267
|
+
dataView: this.dataView,
|
|
268
|
+
parent: this.rowDetailViewOptions?.parent,
|
|
269
|
+
} as ViewModelBindableInputData;
|
|
270
|
+
const viewObj = this._views.find(obj => obj.id === item[this.datasetIdPropName]);
|
|
271
|
+
|
|
272
|
+
// load our Row Detail React Component dynamically, typically we would want to use `root.render()` after the preload component (last argument below)
|
|
273
|
+
// 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
|
|
274
|
+
// that is the only way I got it working so let's use it anyway and console warnings are removed in production anyway
|
|
275
|
+
const { root } = await loadReactComponentDynamically(this._component, containerElements[containerElements.length - 1] as HTMLElement, bindableData /*, viewObj?.root */);
|
|
276
|
+
if (!viewObj) {
|
|
277
|
+
this.addViewInfoToViewsRef(item, root);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
// --
|
|
283
|
+
// protected functions
|
|
284
|
+
// ------------------
|
|
285
|
+
|
|
286
|
+
protected addViewInfoToViewsRef(item: any, root: Root | null) {
|
|
287
|
+
const viewInfo: CreatedView = {
|
|
288
|
+
id: item[this.datasetIdPropName],
|
|
289
|
+
dataContext: item,
|
|
290
|
+
root
|
|
291
|
+
};
|
|
292
|
+
const idPropName = this.gridOptions.datasetIdPropertyName || 'id';
|
|
293
|
+
addToArrayWhenNotExists(this._views, viewInfo, idPropName);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
protected disposeViewComponent(expandedView: CreatedView): CreatedView | void {
|
|
297
|
+
if (expandedView) {
|
|
298
|
+
if (expandedView?.root) {
|
|
299
|
+
const container = this.gridContainerElement.getElementsByClassName(`${ROW_DETAIL_CONTAINER_PREFIX}${this._views[0].id}`);
|
|
300
|
+
if (container?.length) {
|
|
301
|
+
expandedView.root.unmount();
|
|
302
|
+
container[0].textContent = '';
|
|
303
|
+
return expandedView;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Just before the row get expanded or collapsed we will do the following
|
|
311
|
+
* First determine if the row is expanding or collapsing,
|
|
312
|
+
* if it's expanding we will add it to our View Components reference array if we don't already have it
|
|
313
|
+
* or if it's collapsing we will remove it from our View Components reference array
|
|
314
|
+
*/
|
|
315
|
+
protected handleOnBeforeRowDetailToggle(_e: SlickEventData<OnBeforeRowDetailToggleArgs>, args: { grid: SlickGrid; item: any; }) {
|
|
316
|
+
// expanding
|
|
317
|
+
if (args?.item?.__collapsed) {
|
|
318
|
+
// expanding row detail
|
|
319
|
+
this.addViewInfoToViewsRef(args.item, null);
|
|
320
|
+
} else {
|
|
321
|
+
// collapsing, so dispose of the View
|
|
322
|
+
const foundViewIdx = this._views.findIndex((view: CreatedView) => view.id === args.item[this.datasetIdPropName]);
|
|
323
|
+
if (foundViewIdx >= 0 && this.disposeViewComponent(this._views[foundViewIdx])) {
|
|
324
|
+
this._views.splice(foundViewIdx, 1);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
/** When Row comes back to Viewport Range, we need to redraw the View */
|
|
330
|
+
protected async handleOnRowBackToViewportRange(_e: SlickEventData<OnRowBackToViewportRangeArgs>, args: {
|
|
331
|
+
item: any;
|
|
332
|
+
rowId: string | number;
|
|
333
|
+
rowIndex: number;
|
|
334
|
+
expandedRows: (string | number)[];
|
|
335
|
+
rowIdsOutOfViewport: (string | number)[];
|
|
336
|
+
grid: SlickGrid;
|
|
337
|
+
}) {
|
|
338
|
+
if (args?.item) {
|
|
339
|
+
await this.redrawAllViewComponents();
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* notify the onAsyncResponse with the "args.item" (required property)
|
|
345
|
+
* the plugin will then use item to populate the row detail panel with the "postTemplate"
|
|
346
|
+
* @param item
|
|
347
|
+
*/
|
|
348
|
+
protected notifyTemplate(item: any) {
|
|
349
|
+
if (this.onAsyncResponse) {
|
|
350
|
+
this.onAsyncResponse.notify({ item, itemDetail: item }, new SlickEventData(), this);
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* On Processing, we will notify the plugin with the new item detail once backend server call completes
|
|
356
|
+
* @param item
|
|
357
|
+
*/
|
|
358
|
+
protected async onProcessing(item: any) {
|
|
359
|
+
if (item && typeof this._userProcessFn === 'function') {
|
|
360
|
+
let awaitedItemDetail: any;
|
|
361
|
+
const userProcessFn = this._userProcessFn(item);
|
|
362
|
+
|
|
363
|
+
// wait for the "userProcessFn", once resolved we will save it into the "collection"
|
|
364
|
+
const response: any | any[] = await userProcessFn;
|
|
365
|
+
|
|
366
|
+
if (response.hasOwnProperty(this.datasetIdPropName)) {
|
|
367
|
+
awaitedItemDetail = response; // from Promise
|
|
368
|
+
} else if (response instanceof Response && typeof response['json'] === 'function') {
|
|
369
|
+
awaitedItemDetail = await response['json'](); // from Fetch
|
|
370
|
+
} else if (response && response['content']) {
|
|
371
|
+
awaitedItemDetail = response['content']; // from http-client
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
if (!awaitedItemDetail || !awaitedItemDetail.hasOwnProperty(this.datasetIdPropName)) {
|
|
375
|
+
throw new Error('[Slickgrid-React] could not process the Row Detail, please make sure that your "process" callback ' +
|
|
376
|
+
'(a Promise or an HttpClient call returning an Observable) returns an item object that has an "${this.datasetIdPropName}" property');
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// notify the plugin with the new item details
|
|
380
|
+
this.notifyTemplate(awaitedItemDetail || {});
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type Column, DelimiterType, EventNamingStyle, FileType, Filters, OperatorType, type TreeDataOption } from '@slickgrid-universal/common';
|
|
2
|
-
import type { GridOption } from './models/index';
|
|
2
|
+
import type { GridOption, RowDetailView } from './models/index';
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Default Options that can be passed to the Slickgrid-React
|
|
@@ -227,6 +227,15 @@ export const GlobalGridOptions: Partial<GridOption> = {
|
|
|
227
227
|
pageSize: 25,
|
|
228
228
|
totalItems: 0
|
|
229
229
|
},
|
|
230
|
+
rowDetailView: {
|
|
231
|
+
collapseAllOnSort: true,
|
|
232
|
+
cssClass: 'detail-view-toggle',
|
|
233
|
+
panelRows: 1,
|
|
234
|
+
keyPrefix: '__',
|
|
235
|
+
useRowClick: false,
|
|
236
|
+
useSimpleViewportCalc: true,
|
|
237
|
+
saveDetailViewOnScroll: false,
|
|
238
|
+
} as RowDetailView,
|
|
230
239
|
headerRowHeight: 35,
|
|
231
240
|
rowHeight: 35,
|
|
232
241
|
topPanelHeight: 30,
|