angular-slickgrid 3.3.2 → 4.1.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.
Files changed (55) hide show
  1. package/README.md +180 -188
  2. package/angular-slickgrid.d.ts +1 -3
  3. package/app/modules/angular-slickgrid/components/angular-slickgrid.component.d.ts +9 -6
  4. package/app/modules/angular-slickgrid/extensions/index.d.ts +1 -1
  5. package/app/modules/angular-slickgrid/extensions/{rowDetailViewExtension.d.ts → slickRowDetailView.d.ts} +40 -27
  6. package/app/modules/angular-slickgrid/index.d.ts +1 -1
  7. package/app/modules/angular-slickgrid/models/angularGridInstance.interface.d.ts +1 -1
  8. package/app/modules/angular-slickgrid/modules/angular-slickgrid.module.d.ts +7 -0
  9. package/app/modules/angular-slickgrid/services/angularUtil.service.d.ts +3 -0
  10. package/app/modules/angular-slickgrid/services/bsDropdown.service.d.ts +3 -0
  11. package/app/modules/angular-slickgrid/services/container.service.d.ts +3 -0
  12. package/app/modules/angular-slickgrid/services/translater.service.d.ts +3 -0
  13. package/docs/assets/lib/multiple-select/README.md +17 -0
  14. package/esm2020/angular-slickgrid.mjs +5 -0
  15. package/esm2020/app/modules/angular-slickgrid/components/angular-slickgrid.component.mjs +1168 -0
  16. package/{esm2015/app/modules/angular-slickgrid/constants.js → esm2020/app/modules/angular-slickgrid/constants.mjs} +0 -0
  17. package/{esm2015/app/modules/angular-slickgrid/extensions/index.js → esm2020/app/modules/angular-slickgrid/extensions/index.mjs} +2 -2
  18. package/esm2020/app/modules/angular-slickgrid/extensions/slickRowDetailView.mjs +300 -0
  19. package/esm2020/app/modules/angular-slickgrid/global-grid-options.mjs +243 -0
  20. package/{esm2015/app/modules/angular-slickgrid/index.js → esm2020/app/modules/angular-slickgrid/index.mjs} +2 -2
  21. package/{esm2015/app/modules/angular-slickgrid/models/angularComponentOutput.interface.js → esm2020/app/modules/angular-slickgrid/models/angularComponentOutput.interface.mjs} +0 -0
  22. package/esm2020/app/modules/angular-slickgrid/models/angularGridInstance.interface.mjs +2 -0
  23. package/{esm2015/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.js → esm2020/app/modules/angular-slickgrid/models/externalTestingDependencies.interface.mjs} +0 -0
  24. package/{esm2015/app/modules/angular-slickgrid/models/gridOption.interface.js → esm2020/app/modules/angular-slickgrid/models/gridOption.interface.mjs} +0 -0
  25. package/{esm2015/app/modules/angular-slickgrid/models/index.js → esm2020/app/modules/angular-slickgrid/models/index.mjs} +0 -0
  26. package/{esm2015/app/modules/angular-slickgrid/models/rowDetailView.interface.js → esm2020/app/modules/angular-slickgrid/models/rowDetailView.interface.mjs} +0 -0
  27. package/{esm2015/app/modules/angular-slickgrid/models/slickGrid.interface.js → esm2020/app/modules/angular-slickgrid/models/slickGrid.interface.mjs} +0 -0
  28. package/esm2020/app/modules/angular-slickgrid/modules/angular-slickgrid.module.mjs +46 -0
  29. package/esm2020/app/modules/angular-slickgrid/services/angularUtil.service.mjs +46 -0
  30. package/esm2020/app/modules/angular-slickgrid/services/bsDropdown.service.mjs +103 -0
  31. package/esm2020/app/modules/angular-slickgrid/services/container.service.mjs +26 -0
  32. package/{esm2015/app/modules/angular-slickgrid/services/index.js → esm2020/app/modules/angular-slickgrid/services/index.mjs} +0 -0
  33. package/esm2020/app/modules/angular-slickgrid/services/translater.service.mjs +43 -0
  34. package/{esm2015/app/modules/angular-slickgrid/services/utilities.js → esm2020/app/modules/angular-slickgrid/services/utilities.mjs} +0 -0
  35. package/{esm2015/app/modules/angular-slickgrid/slickgrid-config.js → esm2020/app/modules/angular-slickgrid/slickgrid-config.mjs} +0 -0
  36. package/{esm2015/public_api.js → esm2020/public_api.mjs} +0 -0
  37. package/fesm2015/{angular-slickgrid.js → angular-slickgrid.mjs} +252 -282
  38. package/fesm2015/angular-slickgrid.mjs.map +1 -0
  39. package/fesm2020/angular-slickgrid.mjs +2066 -0
  40. package/fesm2020/angular-slickgrid.mjs.map +1 -0
  41. package/package.json +38 -23
  42. package/angular-slickgrid.metadata.json +0 -1
  43. package/bundles/angular-slickgrid.umd.js +0 -2642
  44. package/bundles/angular-slickgrid.umd.js.map +0 -1
  45. package/esm2015/angular-slickgrid.js +0 -7
  46. package/esm2015/app/modules/angular-slickgrid/components/angular-slickgrid.component.js +0 -1202
  47. package/esm2015/app/modules/angular-slickgrid/extensions/rowDetailViewExtension.js +0 -342
  48. package/esm2015/app/modules/angular-slickgrid/global-grid-options.js +0 -243
  49. package/esm2015/app/modules/angular-slickgrid/models/angularGridInstance.interface.js +0 -2
  50. package/esm2015/app/modules/angular-slickgrid/modules/angular-slickgrid.module.js +0 -37
  51. package/esm2015/app/modules/angular-slickgrid/services/angularUtil.service.js +0 -48
  52. package/esm2015/app/modules/angular-slickgrid/services/bsDropdown.service.js +0 -103
  53. package/esm2015/app/modules/angular-slickgrid/services/container.service.js +0 -24
  54. package/esm2015/app/modules/angular-slickgrid/services/translater.service.js +0 -47
  55. package/fesm2015/angular-slickgrid.js.map +0 -1
@@ -0,0 +1,2066 @@
1
+ import { unsubscribeAll, SlickRowSelectionModel, castObservableToPromise, addToArrayWhenNotExists, Filters, OperatorType, EventNamingStyle, FileType, DelimiterType, SlickgridConfig as SlickgridConfig$1, BackendUtilityService, GridEventService, SharedService, CollectionService, ExtensionUtility, FilterFactory, FilterService, ResizerService, SortService, TreeDataService, PaginationService, ExtensionService, GridStateService, GridService, GroupingAndColspanService, emptyElement, SlickGroupItemMetadataProvider, autoAddEditorFormatterToColumnsWithEditor, GridStateType, ExtensionName } from '@slickgrid-universal/common';
2
+ export * from '@slickgrid-universal/common';
3
+ import * as i0 from '@angular/core';
4
+ import { Injectable, Optional, ApplicationRef, Component, Inject, Input, NgModule } from '@angular/core';
5
+ import * as i1 from '@ngx-translate/core';
6
+ import { TranslateModule } from '@ngx-translate/core';
7
+ import 'slickgrid/plugins/slick.rowdetailview';
8
+ import 'slickgrid/plugins/slick.rowselectionmodel';
9
+ import { SlickRowDetailView as SlickRowDetailView$1 } from '@slickgrid-universal/row-detail-view-plugin';
10
+ import { Observable } from 'rxjs';
11
+ import * as DOMPurify from 'dompurify';
12
+ import 'jquery-ui/ui/widgets/draggable';
13
+ import 'jquery-ui/ui/widgets/droppable';
14
+ import 'jquery-ui/ui/widgets/sortable';
15
+ import 'slickgrid/lib/jquery.event.drag-2.3.0';
16
+ import 'slickgrid/lib/jquery.mousewheel';
17
+ import 'slickgrid/slick.core';
18
+ import 'slickgrid/slick.grid';
19
+ import 'slickgrid/slick.dataview';
20
+ import { EventPubSubService } from '@slickgrid-universal/event-pub-sub';
21
+ import { SlickEmptyWarningComponent } from '@slickgrid-universal/empty-warning-component';
22
+ import { SlickFooterComponent } from '@slickgrid-universal/custom-footer-component';
23
+ import { SlickPaginationComponent } from '@slickgrid-universal/pagination-component';
24
+ import { RxJsResource } from '@slickgrid-universal/rxjs-observable';
25
+ import { dequal } from 'dequal/lite';
26
+ import { CommonModule } from '@angular/common';
27
+
28
+ class AngularUtilService {
29
+ constructor(compFactoryResolver, appRef, injector) {
30
+ this.compFactoryResolver = compFactoryResolver;
31
+ this.appRef = appRef;
32
+ this.injector = injector;
33
+ }
34
+ // ref https://hackernoon.com/angular-pro-tip-how-to-dynamically-create-components-in-body-ba200cc289e6
35
+ createAngularComponent(component) {
36
+ // Create a component reference from the component
37
+ const componentRef = this.compFactoryResolver
38
+ .resolveComponentFactory(component)
39
+ .create(this.injector);
40
+ // Attach component to the appRef so that it's inside the ng component tree
41
+ this.appRef.attachView(componentRef.hostView);
42
+ // Get DOM element from component
43
+ let domElem;
44
+ const viewRef = componentRef.hostView;
45
+ if (viewRef && Array.isArray(viewRef.rootNodes) && viewRef.rootNodes[0]) {
46
+ domElem = viewRef.rootNodes[0];
47
+ }
48
+ return { componentRef, domElement: domElem };
49
+ }
50
+ // ref https://hackernoon.com/angular-pro-tip-how-to-dynamically-create-components-in-body-ba200cc289e6
51
+ createAngularComponentAppendToDom(component, targetElement, clearTargetContent = false) {
52
+ const componentOutput = this.createAngularComponent(component);
53
+ // Append DOM element to the HTML element specified
54
+ if (targetElement && targetElement.appendChild) {
55
+ if (clearTargetContent && targetElement.innerHTML) {
56
+ targetElement.innerHTML = '';
57
+ }
58
+ targetElement.appendChild(componentOutput.domElement);
59
+ }
60
+ else {
61
+ document.body.appendChild(componentOutput.domElement); // when no target provided, we'll simply add it to the HTML Body
62
+ }
63
+ return componentOutput;
64
+ }
65
+ }
66
+ AngularUtilService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: AngularUtilService, deps: [{ token: i0.ComponentFactoryResolver }, { token: i0.ApplicationRef }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable });
67
+ AngularUtilService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: AngularUtilService });
68
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: AngularUtilService, decorators: [{
69
+ type: Injectable
70
+ }], ctorParameters: function () { return [{ type: i0.ComponentFactoryResolver }, { type: i0.ApplicationRef }, { type: i0.Injector }]; } });
71
+
72
+ // Boostrap dropdown service
73
+ class BsDropDownService {
74
+ constructor(angularUtilService) {
75
+ this.angularUtilService = angularUtilService;
76
+ }
77
+ get domElement() {
78
+ return this._domElement;
79
+ }
80
+ get domContainerElement() {
81
+ return this._domContainerElement;
82
+ }
83
+ get gridViewport() {
84
+ return $('.slick-viewport');
85
+ }
86
+ dispose() {
87
+ if (this._domElement && this._domElement.remove) {
88
+ this._domElement.remove();
89
+ }
90
+ }
91
+ dropContainerShow() {
92
+ if (this._domContainerElement && this._domContainerElement.show) {
93
+ this._domContainerElement.show();
94
+ }
95
+ }
96
+ render(dropdownParams) {
97
+ return new Promise((resolve) => {
98
+ const { component, args, parent, offsetTop, offsetLeft, offsetDropupBottom } = dropdownParams;
99
+ const cell = args.cell;
100
+ const row = args.row;
101
+ this._domContainerElement = $(`#myDrop-r${row}-c${cell}`);
102
+ if (this._domContainerElement) {
103
+ // hide the dropdown we created as a formatter Component, we'll redisplay it later
104
+ const cellPos = this._domContainerElement.offset();
105
+ const componentOutput = this.angularUtilService.createAngularComponent(component);
106
+ const componentInstance = componentOutput && componentOutput.componentRef && componentOutput.componentRef.instance;
107
+ if (componentInstance) {
108
+ const myDropId = componentInstance.dropdownId || 'myDrop';
109
+ const dropDownToggleId = componentInstance.dropDownToggleId || 'dropdownMenu1';
110
+ this._domElement = $(`#${myDropId}`);
111
+ if (this._domElement) {
112
+ // make sure to remove any previous Action dropdown elements, to avoid having multiple element of the same on top of each other
113
+ this.dispose();
114
+ // assign the row data to the dropdown component instance
115
+ Object.assign(componentInstance, { parent, row: args.row, dataContext: args.grid.getDataItem(args.row) });
116
+ // use a delay to make sure Angular ran at least a full cycle and make sure it finished rendering the Component before using it
117
+ setTimeout(() => {
118
+ // create a new dropdown element
119
+ this._domElement = $(componentOutput.domElement);
120
+ const topPos = (cellPos && cellPos.top || 0) + 30 + (offsetTop || 0);
121
+ const leftPos = (cellPos && cellPos.left || 0) + (offsetLeft || 0);
122
+ this._domElement.appendTo('body');
123
+ this._domElement.css('position', 'absolute');
124
+ this._domElement.css('top', topPos);
125
+ this._domElement.css('left', leftPos);
126
+ $(`#${myDropId}`).addClass('open');
127
+ $(`#${dropDownToggleId}`).hide();
128
+ // check if it should drop Up or Down
129
+ const offset = 35;
130
+ const iElement = $('.dropdown-menu');
131
+ const iElementWrapper = iElement.parent();
132
+ const iElementWrapperOffset = iElementWrapper.offset() || {};
133
+ const iElementWrapperOffsetTop = iElementWrapperOffset.top || iElementWrapper && iElementWrapper.length > 0 && iElementWrapper[0].offsetTop;
134
+ const iElementHeight = iElement.height();
135
+ const windowHeight = window.innerHeight;
136
+ const shouldDropUp = (windowHeight - iElementHeight - offset) < iElementWrapperOffsetTop;
137
+ let menuMarginTop = '0px';
138
+ if (shouldDropUp) {
139
+ const offsetBottom = offsetDropupBottom || 0;
140
+ menuMarginTop = '-'.concat(`${iElementHeight + offset + offsetBottom + 5}`, 'px');
141
+ }
142
+ this._domElement.css({ 'margin-top': menuMarginTop });
143
+ // set dropdown margin left according to the document width
144
+ const parentOffset = iElementWrapperOffset.left;
145
+ const leftMargin = parentOffset - $(document).width();
146
+ this._domElement.css({ 'margin-left': (this._domElement.width() + leftMargin + 60) + 'px' });
147
+ try {
148
+ this._domElement.dropdown('show'); // required for Bootstrap 4 only
149
+ }
150
+ catch (e) {
151
+ // Bootstrap 3 wil throw an error since that method doesn't exist, we can safely disregard it
152
+ }
153
+ this._domElement.on('hidden.bs.dropdown', () => this.dropContainerShow());
154
+ // hide dropdown menu on grid scroll
155
+ this.gridViewport.on('scroll', () => this.dispose());
156
+ // hide on dropdown click
157
+ this._domElement.on('click', () => this.dispose());
158
+ resolve(true);
159
+ });
160
+ }
161
+ }
162
+ }
163
+ });
164
+ }
165
+ }
166
+ BsDropDownService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: BsDropDownService, deps: [{ token: AngularUtilService }], target: i0.ɵɵFactoryTarget.Injectable });
167
+ BsDropDownService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: BsDropDownService });
168
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: BsDropDownService, decorators: [{
169
+ type: Injectable
170
+ }], ctorParameters: function () { return [{ type: AngularUtilService }]; } });
171
+
172
+ class ContainerService {
173
+ constructor() {
174
+ this.dependencies = [];
175
+ }
176
+ get(key) {
177
+ const dependency = this.dependencies.find(dep => dep.key === key);
178
+ if (dependency?.instance) {
179
+ return dependency.instance;
180
+ }
181
+ return null;
182
+ }
183
+ registerInstance(key, instance) {
184
+ const dependency = this.dependencies.some(dep => dep.key === key);
185
+ if (!dependency) {
186
+ this.dependencies.push({ key, instance });
187
+ }
188
+ }
189
+ }
190
+ ContainerService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: ContainerService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
191
+ ContainerService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: ContainerService });
192
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: ContainerService, decorators: [{
193
+ type: Injectable
194
+ }], ctorParameters: function () { return []; } });
195
+
196
+ /**
197
+ * This is a Translate Service Wrapper for Slickgrid-Universal monorepo lib to work properly,
198
+ * it must implement Slickgrid-Universal TranslaterService interface to work properly
199
+ */
200
+ class TranslaterService {
201
+ constructor(translateService) {
202
+ this.translateService = translateService;
203
+ }
204
+ /**
205
+ * Method to return the current language used by the App
206
+ * @return {string} current language
207
+ */
208
+ getCurrentLanguage() {
209
+ return this.translateService?.currentLang ?? '';
210
+ }
211
+ /**
212
+ * Method to set the language to use in the App and Translate Service
213
+ * @param {string} language
214
+ * @return {Promise} output
215
+ */
216
+ async use(newLang) {
217
+ return this.translateService?.use?.(newLang);
218
+ }
219
+ /**
220
+ * Method which receives a translation key and returns the translated value assigned to that key
221
+ * @param {string} translation key
222
+ * @return {string} translated value
223
+ */
224
+ translate(translationKey) {
225
+ return this.translateService?.instant?.(translationKey || ' ');
226
+ }
227
+ }
228
+ TranslaterService.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: TranslaterService, deps: [{ token: i1.TranslateService, optional: true }], target: i0.ɵɵFactoryTarget.Injectable });
229
+ TranslaterService.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: TranslaterService });
230
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: TranslaterService, decorators: [{
231
+ type: Injectable
232
+ }], ctorParameters: function () { return [{ type: i1.TranslateService, decorators: [{
233
+ type: Optional
234
+ }] }]; } });
235
+
236
+ /**
237
+ * Unsubscribe all Observables Subscriptions
238
+ * It will return an empty array if it all went well
239
+ * @param subscriptions
240
+ */
241
+ function unsubscribeAllObservables(subscriptions) {
242
+ if (Array.isArray(subscriptions)) {
243
+ subscriptions.forEach((subscription) => {
244
+ if (subscription && subscription.unsubscribe) {
245
+ subscription.unsubscribe();
246
+ }
247
+ });
248
+ subscriptions = [];
249
+ }
250
+ return subscriptions;
251
+ }
252
+
253
+ const ROW_DETAIL_CONTAINER_PREFIX = 'container_';
254
+ const PRELOAD_CONTAINER_PREFIX = 'container_loading';
255
+ class SlickRowDetailView extends SlickRowDetailView$1 {
256
+ constructor(angularUtilService, appRef, eventPubSubService, gridContainerElement, rxjs) {
257
+ super();
258
+ this.angularUtilService = angularUtilService;
259
+ this.appRef = appRef;
260
+ this.eventPubSubService = eventPubSubService;
261
+ this.gridContainerElement = gridContainerElement;
262
+ this.rxjs = rxjs;
263
+ this._views = [];
264
+ this._subscriptions = [];
265
+ }
266
+ get addonOptions() {
267
+ return this.getOptions();
268
+ }
269
+ get datasetIdPropName() {
270
+ return this.gridOptions.datasetIdPropertyName || 'id';
271
+ }
272
+ get eventHandler() {
273
+ return this._eventHandler;
274
+ }
275
+ set eventHandler(eventHandler) {
276
+ this._eventHandler = eventHandler;
277
+ }
278
+ /** Getter for the Grid Options pulled through the Grid Object */
279
+ get gridOptions() {
280
+ return (this._grid?.getOptions() || {});
281
+ }
282
+ get rowDetailViewOptions() {
283
+ return this.gridOptions.rowDetailView;
284
+ }
285
+ addRxJsResource(rxjs) {
286
+ this.rxjs = rxjs;
287
+ }
288
+ /** Dispose of the RowDetailView Extension */
289
+ dispose() {
290
+ this.disposeAllViewComponents();
291
+ this._subscriptions = unsubscribeAll(this._subscriptions); // also unsubscribe all RxJS subscriptions
292
+ super.dispose();
293
+ }
294
+ /** Dispose of all the opened Row Detail Panels Angular View Components */
295
+ disposeAllViewComponents() {
296
+ this._views.forEach((compRef) => this.disposeViewComponent(compRef));
297
+ this._views = [];
298
+ }
299
+ /** Get the instance of the SlickGrid addon (control or plugin). */
300
+ getAddonInstance() {
301
+ return this;
302
+ }
303
+ init(grid) {
304
+ this._grid = grid;
305
+ super.init(this._grid);
306
+ this.register(grid?.getSelectionModel());
307
+ }
308
+ /**
309
+ * Create the plugin before the Grid creation, else it will behave oddly.
310
+ * Mostly because the column definitions might change after the grid creation
311
+ */
312
+ register(rowSelectionPlugin) {
313
+ if (typeof this.gridOptions.rowDetailView?.process === 'function') {
314
+ // we need to keep the user "process" method and replace it with our own execution method
315
+ // we do this because when we get the item detail, we need to call "onAsyncResponse.notify" for the plugin to work
316
+ this._userProcessFn = this.gridOptions.rowDetailView.process; // keep user's process method
317
+ this.gridOptions.rowDetailView.process = (item) => this.onProcessing(item); // replace process method & run our internal one
318
+ }
319
+ else {
320
+ throw new Error('[Angular-Slickgrid] You need to provide a "process" function for the Row Detail Extension to work properly');
321
+ }
322
+ if (this._grid && this.gridOptions?.rowDetailView) {
323
+ // load the Preload & RowDetail Templates (could be straight HTML or Angular View/ViewModel)
324
+ // when those are Angular View/ViewModel, we need to create View Component & provide the html containers to the Plugin (preTemplate/postTemplate methods)
325
+ if (!this.gridOptions.rowDetailView.preTemplate) {
326
+ this._preloadComponent = this.gridOptions?.rowDetailView?.preloadComponent;
327
+ this.gridOptions.rowDetailView.preTemplate = () => DOMPurify.sanitize(`<div class="${PRELOAD_CONTAINER_PREFIX}"></div>`);
328
+ }
329
+ if (!this.gridOptions.rowDetailView.postTemplate) {
330
+ this._viewComponent = this.gridOptions?.rowDetailView?.viewComponent;
331
+ this.gridOptions.rowDetailView.postTemplate = (itemDetail) => DOMPurify.sanitize(`<div class="${ROW_DETAIL_CONTAINER_PREFIX}${itemDetail[this.datasetIdPropName]}"></div>`);
332
+ }
333
+ // this also requires the Row Selection Model to be registered as well
334
+ if (!rowSelectionPlugin || !this._grid.getSelectionModel()) {
335
+ rowSelectionPlugin = new SlickRowSelectionModel(this.gridOptions.rowSelectionOptions || { selectActiveRow: true });
336
+ this._grid.setSelectionModel(rowSelectionPlugin);
337
+ }
338
+ // hook all events
339
+ if (this._grid && this.rowDetailViewOptions) {
340
+ if (this.rowDetailViewOptions.onExtensionRegistered) {
341
+ this.rowDetailViewOptions.onExtensionRegistered(this);
342
+ }
343
+ if (this.onAsyncResponse) {
344
+ this._eventHandler.subscribe(this.onAsyncResponse, (event, args) => {
345
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAsyncResponse === 'function') {
346
+ this.rowDetailViewOptions.onAsyncResponse(event, args);
347
+ }
348
+ });
349
+ }
350
+ if (this.onAsyncEndUpdate) {
351
+ this._eventHandler.subscribe(this.onAsyncEndUpdate, (e, args) => {
352
+ // triggers after backend called "onAsyncResponse.notify()"
353
+ this.renderViewModel(args?.item);
354
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAsyncEndUpdate === 'function') {
355
+ this.rowDetailViewOptions.onAsyncEndUpdate(e, args);
356
+ }
357
+ });
358
+ }
359
+ if (this.onAfterRowDetailToggle) {
360
+ this._eventHandler.subscribe(this.onAfterRowDetailToggle, (e, args) => {
361
+ // display preload template & re-render all the other Detail Views after toggling
362
+ // the preload View will eventually go away once the data gets loaded after the "onAsyncEndUpdate" event
363
+ this.renderPreloadView();
364
+ this.renderAllViewComponents();
365
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAfterRowDetailToggle === 'function') {
366
+ this.rowDetailViewOptions.onAfterRowDetailToggle(e, args);
367
+ }
368
+ });
369
+ }
370
+ if (this.onBeforeRowDetailToggle) {
371
+ this._eventHandler.subscribe(this.onBeforeRowDetailToggle, (e, args) => {
372
+ // before toggling row detail, we need to create View Component if it doesn't exist
373
+ this.handleOnBeforeRowDetailToggle(e, args);
374
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onBeforeRowDetailToggle === 'function') {
375
+ this.rowDetailViewOptions.onBeforeRowDetailToggle(e, args);
376
+ }
377
+ });
378
+ }
379
+ if (this.onRowBackToViewportRange) {
380
+ this._eventHandler.subscribe(this.onRowBackToViewportRange, (e, args) => {
381
+ // when row is back to viewport range, we will re-render the View Component(s)
382
+ this.handleOnRowBackToViewportRange(e, args);
383
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onRowBackToViewportRange === 'function') {
384
+ this.rowDetailViewOptions.onRowBackToViewportRange(e, args);
385
+ }
386
+ });
387
+ }
388
+ if (this.onRowOutOfViewportRange) {
389
+ this._eventHandler.subscribe(this.onRowOutOfViewportRange, (e, args) => {
390
+ if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onRowOutOfViewportRange === 'function') {
391
+ this.rowDetailViewOptions.onRowOutOfViewportRange(e, args);
392
+ }
393
+ });
394
+ }
395
+ // --
396
+ // hook some events needed by the Plugin itself
397
+ // we need to redraw the open detail views if we change column position (column reorder)
398
+ this._eventHandler.subscribe(this._grid.onColumnsReordered, this.redrawAllViewComponents.bind(this));
399
+ // on row selection changed, we also need to redraw
400
+ if (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector) {
401
+ this._eventHandler.subscribe(this._grid.onSelectedRowsChanged, this.redrawAllViewComponents.bind(this));
402
+ }
403
+ // on sort, all row detail are collapsed so we can dispose of all the Views as well
404
+ this._eventHandler.subscribe(this._grid.onSort, this.disposeAllViewComponents.bind(this));
405
+ // on filter changed, we need to re-render all Views
406
+ this._subscriptions.push(this.eventPubSubService?.subscribe('onFilterChanged', this.redrawAllViewComponents.bind(this)), this.eventPubSubService?.subscribe('onGridMenuClearAllFilters', () => setTimeout(() => this.redrawAllViewComponents())), this.eventPubSubService?.subscribe('onGridMenuClearAllSorting', () => setTimeout(() => this.redrawAllViewComponents())));
407
+ }
408
+ }
409
+ return this;
410
+ }
411
+ /** Redraw (re-render) all the expanded row detail View Components */
412
+ redrawAllViewComponents() {
413
+ this._views.forEach((compRef) => {
414
+ this.redrawViewComponent(compRef);
415
+ });
416
+ }
417
+ /** Render all the expanded row detail View Components */
418
+ renderAllViewComponents() {
419
+ this._views.forEach((view) => {
420
+ if (view && view.dataContext) {
421
+ this.renderViewModel(view.dataContext);
422
+ }
423
+ });
424
+ }
425
+ /** Redraw the necessary View Component */
426
+ redrawViewComponent(createdView) {
427
+ const containerElements = this.gridContainerElement.getElementsByClassName(`${ROW_DETAIL_CONTAINER_PREFIX}${createdView.id}`);
428
+ if (containerElements && containerElements.length >= 0) {
429
+ this.renderViewModel(createdView.dataContext);
430
+ }
431
+ }
432
+ /** Render (or re-render) the View Component (Row Detail) */
433
+ renderPreloadView() {
434
+ const containerElements = this.gridContainerElement.getElementsByClassName(`${PRELOAD_CONTAINER_PREFIX}`);
435
+ if (containerElements && containerElements.length >= 0) {
436
+ this.angularUtilService.createAngularComponentAppendToDom(this._preloadComponent, containerElements[containerElements.length - 1], true);
437
+ }
438
+ }
439
+ /** Render (or re-render) the View Component (Row Detail) */
440
+ renderViewModel(item) {
441
+ const containerElements = this.gridContainerElement.getElementsByClassName(`${ROW_DETAIL_CONTAINER_PREFIX}${item[this.datasetIdPropName]}`);
442
+ if (containerElements && containerElements.length > 0) {
443
+ const componentOutput = this.angularUtilService.createAngularComponentAppendToDom(this._viewComponent, containerElements[containerElements.length - 1], true);
444
+ if (componentOutput && componentOutput.componentRef && componentOutput.componentRef.instance) {
445
+ // pass a few properties to the Row Detail template component
446
+ Object.assign(componentOutput.componentRef.instance, {
447
+ model: item,
448
+ addon: this,
449
+ grid: this._grid,
450
+ dataView: this.dataView,
451
+ parent: this.rowDetailViewOptions && this.rowDetailViewOptions.parent,
452
+ });
453
+ const viewObj = this._views.find(obj => obj.id === item[this.datasetIdPropName]);
454
+ if (viewObj) {
455
+ viewObj.componentRef = componentOutput.componentRef;
456
+ }
457
+ return viewObj;
458
+ }
459
+ }
460
+ return undefined;
461
+ }
462
+ // --
463
+ // protected functions
464
+ // ------------------
465
+ disposeViewComponent(expandedView) {
466
+ const compRef = expandedView?.componentRef;
467
+ if (compRef) {
468
+ this.appRef.detachView(compRef.hostView);
469
+ if (compRef?.destroy) {
470
+ compRef.destroy();
471
+ }
472
+ return expandedView;
473
+ }
474
+ }
475
+ /**
476
+ * notify the onAsyncResponse with the "args.item" (required property)
477
+ * the plugin will then use item to populate the row detail panel with the "postTemplate"
478
+ * @param item
479
+ */
480
+ notifyTemplate(item) {
481
+ if (this.onAsyncResponse) {
482
+ this.onAsyncResponse.notify({ item }, undefined, this);
483
+ }
484
+ }
485
+ /**
486
+ * On Processing, we will notify the plugin with the new item detail once backend server call completes
487
+ * @param item
488
+ */
489
+ async onProcessing(item) {
490
+ if (item && typeof this._userProcessFn === 'function') {
491
+ let awaitedItemDetail;
492
+ const userProcessFn = this._userProcessFn(item);
493
+ // wait for the "userProcessFn", once resolved we will save it into the "collection"
494
+ const response = await userProcessFn;
495
+ if (response.hasOwnProperty(this.datasetIdPropName)) {
496
+ awaitedItemDetail = response; // from Promise
497
+ }
498
+ else if (response && response instanceof Observable || response instanceof Promise) {
499
+ awaitedItemDetail = await castObservableToPromise(this.rxjs, response); // from Angular-http-client
500
+ }
501
+ if (!awaitedItemDetail || !awaitedItemDetail.hasOwnProperty(this.datasetIdPropName)) {
502
+ throw new Error(`[Angular-Slickgrid] could not process the Row Detail, you must make sure that your "process" callback
503
+ (a Promise or an HttpClient call returning an Observable) returns an item object that has an "${this.datasetIdPropName}" property`);
504
+ }
505
+ // notify the plugin with the new item details
506
+ this.notifyTemplate(awaitedItemDetail || {});
507
+ }
508
+ }
509
+ /**
510
+ * Just before the row get expanded or collapsed we will do the following
511
+ * First determine if the row is expanding or collapsing,
512
+ * if it's expanding we will add it to our View Components reference array if we don't already have it
513
+ * or if it's collapsing we will remove it from our View Components reference array
514
+ */
515
+ handleOnBeforeRowDetailToggle(e, args) {
516
+ // expanding
517
+ if (args && args.item && args.item.__collapsed) {
518
+ // expanding row detail
519
+ const viewInfo = {
520
+ id: args.item[this.datasetIdPropName],
521
+ dataContext: args.item
522
+ };
523
+ const idPropName = this.gridOptions.datasetIdPropertyName || 'id';
524
+ addToArrayWhenNotExists(this._views, viewInfo, idPropName);
525
+ }
526
+ else {
527
+ // collapsing, so dispose of the View/Component
528
+ const foundViewIndex = this._views.findIndex((view) => view.id === args.item[this.datasetIdPropName]);
529
+ if (foundViewIndex >= 0 && this._views.hasOwnProperty(foundViewIndex)) {
530
+ const compRef = this._views[foundViewIndex].componentRef;
531
+ if (compRef) {
532
+ this.appRef.detachView(compRef.hostView);
533
+ compRef.destroy();
534
+ }
535
+ this._views.splice(foundViewIndex, 1);
536
+ }
537
+ }
538
+ }
539
+ /** When Row comes back to Viewport Range, we need to redraw the View */
540
+ handleOnRowBackToViewportRange(e, args) {
541
+ if (args?.item) {
542
+ this.redrawAllViewComponents();
543
+ }
544
+ }
545
+ }
546
+
547
+ /** Global Grid Options Defaults */
548
+ const GlobalGridOptions = {
549
+ alwaysShowVerticalScroll: true,
550
+ autoEdit: false,
551
+ asyncEditorLoading: false,
552
+ autoFitColumnsOnFirstLoad: true,
553
+ autoResize: {
554
+ applyResizeToContainer: true,
555
+ calculateAvailableSizeBy: 'window',
556
+ bottomPadding: 20,
557
+ minHeight: 180,
558
+ minWidth: 300,
559
+ rightPadding: 0
560
+ },
561
+ cellHighlightCssClass: 'slick-cell-modified',
562
+ checkboxSelector: {
563
+ cssClass: 'slick-cell-checkboxsel'
564
+ },
565
+ columnPicker: {
566
+ fadeSpeed: 0,
567
+ hideForceFitButton: false,
568
+ hideSyncResizeButton: true,
569
+ headerColumnValueExtractor: pickerHeaderColumnValueExtractor
570
+ },
571
+ cellMenu: {
572
+ autoAdjustDrop: true,
573
+ autoAlignSide: true,
574
+ hideCloseButton: true,
575
+ hideCommandSection: false,
576
+ hideOptionSection: false,
577
+ },
578
+ contextMenu: {
579
+ autoAdjustDrop: true,
580
+ autoAlignSide: true,
581
+ hideCloseButton: true,
582
+ hideClearAllGrouping: false,
583
+ hideCollapseAllGroups: false,
584
+ hideCommandSection: false,
585
+ hideCopyCellValueCommand: false,
586
+ hideExpandAllGroups: false,
587
+ hideExportCsvCommand: false,
588
+ hideExportExcelCommand: false,
589
+ hideExportTextDelimitedCommand: true,
590
+ hideMenuOnScroll: true,
591
+ hideOptionSection: false,
592
+ iconCopyCellValueCommand: 'fa fa-clone',
593
+ iconExportCsvCommand: 'fa fa-download',
594
+ iconExportExcelCommand: 'fa fa-file-excel-o text-success',
595
+ iconExportTextDelimitedCommand: 'fa fa-download',
596
+ },
597
+ customFooterOptions: {
598
+ dateFormat: 'YYYY-MM-DD, hh:mm a',
599
+ hideRowSelectionCount: false,
600
+ hideTotalItemCount: false,
601
+ hideLastUpdateTimestamp: true,
602
+ footerHeight: 25,
603
+ leftContainerClass: 'col-xs-12 col-sm-5',
604
+ rightContainerClass: 'col-xs-6 col-sm-7',
605
+ metricSeparator: '|',
606
+ metricTexts: {
607
+ items: 'items',
608
+ itemsKey: 'ITEMS',
609
+ itemsSelected: 'items selected',
610
+ itemsSelectedKey: 'ITEMS_SELECTED',
611
+ of: 'of',
612
+ ofKey: 'OF',
613
+ }
614
+ },
615
+ dataView: {
616
+ syncGridSelection: true,
617
+ syncGridSelectionWithBackendService: false, // but disable it when using backend services
618
+ },
619
+ datasetIdPropertyName: 'id',
620
+ defaultFilter: Filters.input,
621
+ defaultBackendServiceFilterTypingDebounce: 500,
622
+ defaultColumnSortFieldId: 'id',
623
+ defaultFilterPlaceholder: '🔎︎',
624
+ defaultFilterRangeOperator: OperatorType.rangeInclusive,
625
+ editable: false,
626
+ enableAutoResize: true,
627
+ enableAutoSizeColumns: true,
628
+ enableCellNavigation: false,
629
+ enableColumnPicker: true,
630
+ enableColumnReorder: true,
631
+ enableColumnResizeOnDoubleClick: true,
632
+ enableContextMenu: true,
633
+ enableExcelExport: true,
634
+ enableExport: false,
635
+ enableFilterTrimWhiteSpace: false,
636
+ enableGridMenu: true,
637
+ enableHeaderMenu: true,
638
+ enableEmptyDataWarningMessage: true,
639
+ emptyDataWarning: {
640
+ className: 'slick-empty-data-warning',
641
+ message: 'No data to display.',
642
+ messageKey: 'EMPTY_DATA_WARNING_MESSAGE',
643
+ hideFrozenLeftWarning: false,
644
+ hideFrozenRightWarning: false,
645
+ leftViewportMarginLeft: '40%',
646
+ rightViewportMarginLeft: '40%',
647
+ frozenLeftViewportMarginLeft: '0px',
648
+ frozenRightViewportMarginLeft: '40%',
649
+ },
650
+ enableMouseHoverHighlightRow: true,
651
+ enableSorting: true,
652
+ enableTextSelectionOnCells: true,
653
+ eventNamingStyle: EventNamingStyle.camelCase,
654
+ explicitInitialization: true,
655
+ excelExportOptions: {
656
+ addGroupIndentation: true,
657
+ exportWithFormatter: false,
658
+ filename: 'export',
659
+ format: FileType.xlsx,
660
+ groupingColumnHeaderTitle: 'Group By',
661
+ groupCollapsedSymbol: '⮞',
662
+ groupExpandedSymbol: '⮟',
663
+ groupingAggregatorRowText: '',
664
+ sanitizeDataExport: false,
665
+ },
666
+ exportOptions: {
667
+ delimiter: DelimiterType.comma,
668
+ exportWithFormatter: false,
669
+ filename: 'export',
670
+ format: FileType.csv,
671
+ groupingColumnHeaderTitle: 'Group By',
672
+ groupingAggregatorRowText: '',
673
+ sanitizeDataExport: false,
674
+ useUtf8WithBom: true
675
+ },
676
+ filterTypingDebounce: 0,
677
+ forceFitColumns: false,
678
+ frozenHeaderWidthCalcDifferential: 0,
679
+ gridMenu: {
680
+ dropSide: 'left',
681
+ commandLabels: {
682
+ clearAllFiltersCommandKey: 'CLEAR_ALL_FILTERS',
683
+ clearAllSortingCommandKey: 'CLEAR_ALL_SORTING',
684
+ clearFrozenColumnsCommandKey: 'CLEAR_PINNING',
685
+ exportCsvCommandKey: 'EXPORT_TO_CSV',
686
+ exportExcelCommandKey: 'EXPORT_TO_EXCEL',
687
+ exportTextDelimitedCommandKey: 'EXPORT_TO_TAB_DELIMITED',
688
+ refreshDatasetCommandKey: 'REFRESH_DATASET',
689
+ toggleFilterCommandKey: 'TOGGLE_FILTER_ROW',
690
+ togglePreHeaderCommandKey: 'TOGGLE_PRE_HEADER_ROW',
691
+ },
692
+ hideClearAllFiltersCommand: false,
693
+ hideClearAllSortingCommand: false,
694
+ hideClearFrozenColumnsCommand: true,
695
+ hideExportCsvCommand: false,
696
+ hideExportExcelCommand: false,
697
+ hideExportTextDelimitedCommand: true,
698
+ hideForceFitButton: false,
699
+ hideRefreshDatasetCommand: false,
700
+ hideSyncResizeButton: true,
701
+ hideToggleFilterCommand: false,
702
+ hideTogglePreHeaderCommand: false,
703
+ iconCssClass: 'fa fa-bars',
704
+ iconClearAllFiltersCommand: 'fa fa-filter text-danger',
705
+ iconClearAllSortingCommand: 'fa fa-unsorted text-danger',
706
+ iconClearFrozenColumnsCommand: 'fa fa-times',
707
+ iconExportCsvCommand: 'fa fa-download',
708
+ iconExportExcelCommand: 'fa fa-file-excel-o text-success',
709
+ iconExportTextDelimitedCommand: 'fa fa-download',
710
+ iconRefreshDatasetCommand: 'fa fa-refresh',
711
+ iconToggleFilterCommand: 'fa fa-random',
712
+ iconTogglePreHeaderCommand: 'fa fa-random',
713
+ menuWidth: 16,
714
+ resizeOnShowHeaderRow: true,
715
+ headerColumnValueExtractor: pickerHeaderColumnValueExtractor
716
+ },
717
+ headerMenu: {
718
+ autoAlign: true,
719
+ autoAlignOffset: 12,
720
+ minWidth: 140,
721
+ iconClearFilterCommand: 'fa fa-filter text-danger',
722
+ iconClearSortCommand: 'fa fa-unsorted',
723
+ iconFreezeColumns: 'fa fa-thumb-tack',
724
+ iconSortAscCommand: 'fa fa-sort-amount-asc',
725
+ iconSortDescCommand: 'fa fa-sort-amount-desc',
726
+ iconColumnHideCommand: 'fa fa-times',
727
+ iconColumnResizeByContentCommand: 'fa fa-arrows-h',
728
+ hideColumnResizeByContentCommand: false,
729
+ hideColumnHideCommand: false,
730
+ hideClearFilterCommand: false,
731
+ hideClearSortCommand: false,
732
+ hideFreezeColumnsCommand: true,
733
+ hideSortCommands: false
734
+ },
735
+ headerRowHeight: 35,
736
+ multiColumnSort: true,
737
+ numberedMultiColumnSort: true,
738
+ tristateMultiColumnSort: false,
739
+ sortColNumberInSeparateSpan: true,
740
+ suppressActiveCellChangeOnEdit: true,
741
+ pagination: {
742
+ pageSizes: [10, 15, 20, 25, 30, 40, 50, 75, 100],
743
+ pageSize: 25,
744
+ totalItems: 0
745
+ },
746
+ // technically speaking the Row Detail requires the process & viewComponent but we'll ignore it just to set certain options
747
+ rowDetailView: {
748
+ collapseAllOnSort: true,
749
+ cssClass: 'detail-view-toggle',
750
+ panelRows: 1,
751
+ keyPrefix: '__',
752
+ useRowClick: false,
753
+ useSimpleViewportCalc: true,
754
+ saveDetailViewOnScroll: false,
755
+ },
756
+ rowHeight: 35,
757
+ topPanelHeight: 35,
758
+ translationNamespaceSeparator: ':',
759
+ resetFilterSearchValueAfterOnBeforeCancellation: true,
760
+ resizeByContentOnlyOnFirstLoad: true,
761
+ resizeByContentOptions: {
762
+ alwaysRecalculateColumnWidth: false,
763
+ cellCharWidthInPx: 7.8,
764
+ cellPaddingWidthInPx: 14,
765
+ defaultRatioForStringType: 0.88,
766
+ formatterPaddingWidthInPx: 0,
767
+ maxItemToInspectCellContentWidth: 1000,
768
+ maxItemToInspectSingleColumnWidthByContent: 5000,
769
+ widthToRemoveFromExceededWidthReadjustment: 50,
770
+ },
771
+ treeDataOptions: {
772
+ exportIndentMarginLeft: 5,
773
+ exportIndentationLeadingChar: '͏͏͏͏͏͏͏͏͏·',
774
+ }
775
+ };
776
+ /**
777
+ * Value Extractor for both ColumnPicker & GridMenu Picker
778
+ * when using Column Header Grouping, we'll prefix the column group title
779
+ * else we'll simply return the column name title
780
+ */
781
+ function pickerHeaderColumnValueExtractor(column) {
782
+ const headerGroup = column && column.columnGroup || '';
783
+ if (headerGroup) {
784
+ return headerGroup + ' - ' + column.name;
785
+ }
786
+ return column && column.name || '';
787
+ }
788
+
789
+ class SlickgridConfig {
790
+ constructor() {
791
+ this.options = GlobalGridOptions;
792
+ }
793
+ }
794
+
795
+ class Constants {
796
+ }
797
+ // English Locale texts when using only 1 Locale instead of I18N
798
+ Constants.locales = {
799
+ TEXT_ALL_SELECTED: 'All Selected',
800
+ TEXT_ALL_X_RECORDS_SELECTED: 'All {{x}} records selected',
801
+ TEXT_APPLY_MASS_UPDATE: 'Apply Mass Update',
802
+ TEXT_APPLY_TO_SELECTION: 'Update Selection',
803
+ TEXT_CANCEL: 'Cancel',
804
+ TEXT_CLEAR_ALL_FILTERS: 'Clear all Filters',
805
+ TEXT_CLEAR_ALL_GROUPING: 'Clear all Grouping',
806
+ TEXT_CLEAR_ALL_SORTING: 'Clear all Sorting',
807
+ TEXT_CLEAR_PINNING: 'Unfreeze Columns/Rows',
808
+ TEXT_CLONE: 'Clone',
809
+ TEXT_COLLAPSE_ALL_GROUPS: 'Collapse all Groups',
810
+ TEXT_CONTAINS: 'Contains',
811
+ TEXT_COLUMNS: 'Columns',
812
+ TEXT_COLUMN_RESIZE_BY_CONTENT: 'Resize by Content',
813
+ TEXT_COMMANDS: 'Commands',
814
+ TEXT_COPY: 'Copy',
815
+ TEXT_EQUALS: 'Equals',
816
+ TEXT_EQUAL_TO: 'Equal to',
817
+ TEXT_ENDS_WITH: 'Ends With',
818
+ TEXT_ERROR_EDITABLE_GRID_REQUIRED: 'Your grid must be editable in order to use the Composite Editor Modal.',
819
+ TEXT_ERROR_ENABLE_CELL_NAVIGATION_REQUIRED: 'Composite Editor requires the flag "enableCellNavigation" to be set to True in your Grid Options.',
820
+ TEXT_ERROR_NO_CHANGES_DETECTED: 'Sorry we could not detect any changes.',
821
+ TEXT_ERROR_NO_EDITOR_FOUND: 'We could not find any Editor in your Column Definition.',
822
+ TEXT_ERROR_NO_RECORD_FOUND: 'No records selected for edit or clone operation.',
823
+ TEXT_ERROR_ROW_NOT_EDITABLE: 'Current row is not editable.',
824
+ TEXT_ERROR_ROW_SELECTION_REQUIRED: 'You must select some rows before trying to apply new value(s).',
825
+ TEXT_EXPAND_ALL_GROUPS: 'Expand all Groups',
826
+ TEXT_EXPORT_TO_CSV: 'Export in CSV format',
827
+ TEXT_EXPORT_TO_TEXT_FORMAT: 'Export in Text format (Tab delimited)',
828
+ TEXT_EXPORT_TO_EXCEL: 'Export to Excel',
829
+ TEXT_EXPORT_TO_TAB_DELIMITED: 'Export in Text format (Tab delimited)',
830
+ TEXT_FORCE_FIT_COLUMNS: 'Force fit columns',
831
+ TEXT_FREEZE_COLUMNS: 'Freeze Columns',
832
+ TEXT_GREATER_THAN: 'Greater than',
833
+ TEXT_GREATER_THAN_OR_EQUAL_TO: 'Greater than or equal to',
834
+ TEXT_GROUP_BY: 'Group By',
835
+ TEXT_HIDE_COLUMN: 'Hide Column',
836
+ TEXT_ITEMS: 'items',
837
+ TEXT_ITEMS_PER_PAGE: 'items per page',
838
+ TEXT_ITEMS_SELECTED: 'items selected',
839
+ TEXT_OF: 'of',
840
+ TEXT_OK: 'OK',
841
+ TEXT_LAST_UPDATE: 'Last Update',
842
+ TEXT_LESS_THAN: 'Less than',
843
+ TEXT_LESS_THAN_OR_EQUAL_TO: 'Less than or equal to',
844
+ TEXT_NOT_CONTAINS: 'Not contains',
845
+ TEXT_NOT_EQUAL_TO: 'Not equal to',
846
+ TEXT_PAGE: 'Page',
847
+ TEXT_REFRESH_DATASET: 'Refresh Dataset',
848
+ TEXT_REMOVE_FILTER: 'Remove Filter',
849
+ TEXT_REMOVE_SORT: 'Remove Sort',
850
+ TEXT_SAVE: 'Save',
851
+ TEXT_SELECT_ALL: 'Select All',
852
+ TEXT_SYNCHRONOUS_RESIZE: 'Synchronous resize',
853
+ TEXT_SORT_ASCENDING: 'Sort Ascending',
854
+ TEXT_SORT_DESCENDING: 'Sort Descending',
855
+ TEXT_STARTS_WITH: 'Starts With',
856
+ TEXT_TOGGLE_FILTER_ROW: 'Toggle Filter Row',
857
+ TEXT_TOGGLE_PRE_HEADER_ROW: 'Toggle Pre-Header Row',
858
+ TEXT_X_OF_Y_SELECTED: '# of % selected',
859
+ TEXT_X_OF_Y_MASS_SELECTED: '{{x}} of {{y}} selected',
860
+ };
861
+ Constants.treeDataProperties = {
862
+ CHILDREN_PROP: 'children',
863
+ COLLAPSED_PROP: '__collapsed',
864
+ HAS_CHILDREN_PROP: '__hasChildren',
865
+ TREE_LEVEL_PROP: '__treeLevel',
866
+ PARENT_PROP: '__parentId',
867
+ };
868
+ // some Validation default texts
869
+ Constants.VALIDATION_REQUIRED_FIELD = 'Field is required';
870
+ Constants.VALIDATION_EDITOR_VALID_NUMBER = 'Please enter a valid number';
871
+ Constants.VALIDATION_EDITOR_VALID_INTEGER = 'Please enter a valid integer number';
872
+ Constants.VALIDATION_EDITOR_INTEGER_BETWEEN = 'Please enter a valid integer number between {{minValue}} and {{maxValue}}';
873
+ Constants.VALIDATION_EDITOR_INTEGER_MAX = 'Please enter a valid integer number that is lower than {{maxValue}}';
874
+ Constants.VALIDATION_EDITOR_INTEGER_MAX_INCLUSIVE = 'Please enter a valid integer number that is lower than or equal to {{maxValue}}';
875
+ Constants.VALIDATION_EDITOR_INTEGER_MIN = 'Please enter a valid integer number that is greater than {{minValue}}';
876
+ Constants.VALIDATION_EDITOR_INTEGER_MIN_INCLUSIVE = 'Please enter a valid integer number that is greater than or equal to {{minValue}}';
877
+ Constants.VALIDATION_EDITOR_NUMBER_BETWEEN = 'Please enter a valid number between {{minValue}} and {{maxValue}}';
878
+ Constants.VALIDATION_EDITOR_NUMBER_MAX = 'Please enter a valid number that is lower than {{maxValue}}';
879
+ Constants.VALIDATION_EDITOR_NUMBER_MAX_INCLUSIVE = 'Please enter a valid number that is lower than or equal to {{maxValue}}';
880
+ Constants.VALIDATION_EDITOR_NUMBER_MIN = 'Please enter a valid number that is greater than {{minValue}}';
881
+ Constants.VALIDATION_EDITOR_NUMBER_MIN_INCLUSIVE = 'Please enter a valid number that is greater than or equal to {{minValue}}';
882
+ Constants.VALIDATION_EDITOR_DECIMAL_BETWEEN = 'Please enter a valid number with a maximum of {{maxDecimal}} decimals';
883
+ Constants.VALIDATION_EDITOR_TEXT_LENGTH_BETWEEN = 'Please make sure your text length is between {{minLength}} and {{maxLength}} characters';
884
+ Constants.VALIDATION_EDITOR_TEXT_MAX_LENGTH = 'Please make sure your text is less than {{maxLength}} characters';
885
+ Constants.VALIDATION_EDITOR_TEXT_MAX_LENGTH_INCLUSIVE = 'Please make sure your text is less than or equal to {{maxLength}} characters';
886
+ Constants.VALIDATION_EDITOR_TEXT_MIN_LENGTH = 'Please make sure your text is more than {{minLength}} character(s)';
887
+ Constants.VALIDATION_EDITOR_TEXT_MIN_LENGTH_INCLUSIVE = 'Please make sure your text is at least {{minLength}} character(s)';
888
+
889
+ // import 3rd party vendor libs
890
+ class AngularSlickgridComponent {
891
+ constructor(angularUtilService, appRef, cd, containerService, elm, translate, translaterService, forRootConfig, externalServices) {
892
+ this.angularUtilService = angularUtilService;
893
+ this.appRef = appRef;
894
+ this.cd = cd;
895
+ this.containerService = containerService;
896
+ this.elm = elm;
897
+ this.translate = translate;
898
+ this.translaterService = translaterService;
899
+ this.forRootConfig = forRootConfig;
900
+ this._currentDatasetLength = 0;
901
+ this._eventHandler = new Slick.EventHandler();
902
+ this._hideHeaderRowAfterPageLoad = false;
903
+ this._isGridInitialized = false;
904
+ this._isDatasetInitialized = false;
905
+ this._isDatasetHierarchicalInitialized = false;
906
+ this._isPaginationInitialized = false;
907
+ this._isLocalGrid = true;
908
+ this._registeredResources = [];
909
+ this.groupingDefinition = {};
910
+ this.showPagination = false;
911
+ this.serviceList = [];
912
+ this.totalItems = 0;
913
+ this.subscriptions = [];
914
+ this.gridId = '';
915
+ const slickgridConfig = new SlickgridConfig$1();
916
+ // initialize and assign all Service Dependencies
917
+ this._eventPubSubService = externalServices?.eventPubSubService ?? new EventPubSubService(this.elm.nativeElement);
918
+ this._eventPubSubService.eventNamingStyle = EventNamingStyle.camelCase;
919
+ this.backendUtilityService = externalServices?.backendUtilityService ?? new BackendUtilityService();
920
+ this.gridEventService = externalServices?.gridEventService ?? new GridEventService();
921
+ this.sharedService = externalServices?.sharedService ?? new SharedService();
922
+ this.collectionService = externalServices?.collectionService ?? new CollectionService(this.translaterService);
923
+ this.extensionUtility = externalServices?.extensionUtility ?? new ExtensionUtility(this.sharedService, this.backendUtilityService, this.translaterService);
924
+ this.filterFactory = new FilterFactory(slickgridConfig, this.translaterService, this.collectionService);
925
+ this.filterService = externalServices?.filterService ?? new FilterService(this.filterFactory, this._eventPubSubService, this.sharedService, this.backendUtilityService);
926
+ this.resizerService = externalServices?.resizerService ?? new ResizerService(this._eventPubSubService);
927
+ this.sortService = externalServices?.sortService ?? new SortService(this.sharedService, this._eventPubSubService, this.backendUtilityService);
928
+ this.treeDataService = externalServices?.treeDataService ?? new TreeDataService(this._eventPubSubService, this.sharedService, this.sortService);
929
+ this.paginationService = externalServices?.paginationService ?? new PaginationService(this._eventPubSubService, this.sharedService, this.backendUtilityService);
930
+ this.extensionService = externalServices?.extensionService ?? new ExtensionService(this.extensionUtility, this.filterService, this._eventPubSubService, this.sharedService, this.sortService, this.treeDataService, this.translaterService);
931
+ this.gridStateService = externalServices?.gridStateService ?? new GridStateService(this.extensionService, this.filterService, this._eventPubSubService, this.sharedService, this.sortService, this.treeDataService);
932
+ this.gridService = externalServices?.gridService ?? new GridService(this.gridStateService, this.filterService, this._eventPubSubService, this.paginationService, this.sharedService, this.sortService, this.treeDataService);
933
+ this.groupingService = externalServices?.groupingAndColspanService ?? new GroupingAndColspanService(this.extensionUtility, this._eventPubSubService);
934
+ this.serviceList = [
935
+ this.extensionService,
936
+ this.filterService,
937
+ this.gridEventService,
938
+ this.gridService,
939
+ this.gridStateService,
940
+ this.groupingService,
941
+ this.paginationService,
942
+ this.resizerService,
943
+ this.sortService,
944
+ this.treeDataService,
945
+ ];
946
+ // register all Service instances in the container
947
+ this.containerService.registerInstance('ExtensionUtility', this.extensionUtility);
948
+ this.containerService.registerInstance('FilterService', this.filterService);
949
+ this.containerService.registerInstance('CollectionService', this.collectionService);
950
+ this.containerService.registerInstance('ExtensionService', this.extensionService);
951
+ this.containerService.registerInstance('GridEventService', this.gridEventService);
952
+ this.containerService.registerInstance('GridService', this.gridService);
953
+ this.containerService.registerInstance('GridStateService', this.gridStateService);
954
+ this.containerService.registerInstance('GroupingAndColspanService', this.groupingService);
955
+ this.containerService.registerInstance('PaginationService', this.paginationService);
956
+ this.containerService.registerInstance('ResizerService', this.resizerService);
957
+ this.containerService.registerInstance('SharedService', this.sharedService);
958
+ this.containerService.registerInstance('SortService', this.sortService);
959
+ this.containerService.registerInstance('EventPubSubService', this._eventPubSubService);
960
+ this.containerService.registerInstance('PubSubService', this._eventPubSubService);
961
+ this.containerService.registerInstance('TranslaterService', this.translaterService);
962
+ this.containerService.registerInstance('TreeDataService', this.treeDataService);
963
+ }
964
+ get paginationOptions() {
965
+ return this._paginationOptions;
966
+ }
967
+ set paginationOptions(newPaginationOptions) {
968
+ if (newPaginationOptions && this._paginationOptions) {
969
+ this._paginationOptions = { ...this.gridOptions.pagination, ...this._paginationOptions, ...newPaginationOptions };
970
+ }
971
+ else {
972
+ this._paginationOptions = newPaginationOptions;
973
+ }
974
+ this.gridOptions.pagination = this._paginationOptions ?? this.gridOptions.pagination;
975
+ this.paginationService.updateTotalItems(this.gridOptions.pagination?.totalItems ?? 0, true);
976
+ }
977
+ set columnDefinitions(columnDefinitions) {
978
+ this._columnDefinitions = columnDefinitions;
979
+ if (this._isGridInitialized) {
980
+ this.updateColumnDefinitionsList(columnDefinitions);
981
+ }
982
+ if (columnDefinitions.length > 0) {
983
+ this.copyColumnWidthsReference(columnDefinitions);
984
+ }
985
+ }
986
+ get columnDefinitions() {
987
+ return this._columnDefinitions;
988
+ }
989
+ get dataset() {
990
+ return (this.customDataView ? this.slickGrid?.getData?.() : this.dataView?.getItems?.()) || [];
991
+ }
992
+ set dataset(newDataset) {
993
+ const prevDatasetLn = this._currentDatasetLength;
994
+ const isDatasetEqual = dequal(newDataset, this._dataset || []);
995
+ let data = newDataset;
996
+ // when Tree Data is enabled and we don't yet have the hierarchical dataset filled, we can force a convert+sort of the array
997
+ if (this.slickGrid && this.gridOptions?.enableTreeData && Array.isArray(newDataset) && (newDataset.length > 0 || newDataset.length !== prevDatasetLn || !isDatasetEqual)) {
998
+ this._isDatasetHierarchicalInitialized = false;
999
+ data = this.sortTreeDataset(newDataset, !isDatasetEqual); // if dataset changed, then force a refresh anyway
1000
+ }
1001
+ this._dataset = data;
1002
+ this.refreshGridData(data || []);
1003
+ this._currentDatasetLength = (newDataset || []).length;
1004
+ // expand/autofit columns on first page load
1005
+ // we can assume that if the prevDataset was empty then we are on first load
1006
+ if (this.gridOptions?.autoFitColumnsOnFirstLoad && prevDatasetLn === 0) {
1007
+ this.slickGrid.autosizeColumns();
1008
+ }
1009
+ }
1010
+ get datasetHierarchical() {
1011
+ return this.sharedService.hierarchicalDataset;
1012
+ }
1013
+ set datasetHierarchical(newHierarchicalDataset) {
1014
+ const isDatasetEqual = dequal(newHierarchicalDataset, this.sharedService?.hierarchicalDataset ?? []);
1015
+ const prevFlatDatasetLn = this._currentDatasetLength;
1016
+ this.sharedService.hierarchicalDataset = newHierarchicalDataset;
1017
+ if (newHierarchicalDataset && this.columnDefinitions && this.filterService?.clearFilters) {
1018
+ this.filterService.clearFilters();
1019
+ }
1020
+ // when a hierarchical dataset is set afterward, we can reset the flat dataset and call a tree data sort that will overwrite the flat dataset
1021
+ if (newHierarchicalDataset && this.slickGrid && this.sortService?.processTreeDataInitialSort) {
1022
+ this.dataView.setItems([], this.gridOptions.datasetIdPropertyName ?? 'id');
1023
+ this.sortService.processTreeDataInitialSort();
1024
+ // we also need to reset/refresh the Tree Data filters because if we inserted new item(s) then it might not show up without doing this refresh
1025
+ // however we need 1 cpu cycle before having the DataView refreshed, so we need to wrap this check in a setTimeout
1026
+ setTimeout(() => {
1027
+ const flatDatasetLn = this.dataView.getItemCount();
1028
+ if (flatDatasetLn > 0 && (flatDatasetLn !== prevFlatDatasetLn || !isDatasetEqual)) {
1029
+ this.filterService.refreshTreeDataFilters();
1030
+ }
1031
+ });
1032
+ this._isDatasetHierarchicalInitialized = true;
1033
+ }
1034
+ }
1035
+ get elementRef() {
1036
+ return this.elm;
1037
+ }
1038
+ get eventHandler() {
1039
+ return this._eventHandler;
1040
+ }
1041
+ get gridContainerElement() {
1042
+ return document.querySelector(`#${this.gridOptions.gridContainerId || ''}`);
1043
+ }
1044
+ /** GETTER to know if dataset was initialized or not */
1045
+ get isDatasetInitialized() {
1046
+ return this._isDatasetInitialized;
1047
+ }
1048
+ /** SETTER to change if dataset was initialized or not (stringly used for unit testing purposes) */
1049
+ set isDatasetInitialized(isInitialized) {
1050
+ this._isDatasetInitialized = isInitialized;
1051
+ }
1052
+ set isDatasetHierarchicalInitialized(isInitialized) {
1053
+ this._isDatasetHierarchicalInitialized = isInitialized;
1054
+ }
1055
+ get registeredResources() {
1056
+ return this._registeredResources;
1057
+ }
1058
+ ngAfterViewInit() {
1059
+ this.initialization(this._eventHandler);
1060
+ this._isGridInitialized = true;
1061
+ // recheck the empty warning message after grid is shown so that it works in every use case
1062
+ if (this.gridOptions && this.gridOptions.enableEmptyDataWarningMessage && Array.isArray(this.dataset)) {
1063
+ const finalTotalCount = this.dataset.length;
1064
+ this.displayEmptyDataWarning(finalTotalCount < 1);
1065
+ }
1066
+ }
1067
+ ngOnDestroy() {
1068
+ this._eventPubSubService.publish('onBeforeGridDestroy', this.slickGrid);
1069
+ this.destroy();
1070
+ this._eventPubSubService.publish('onAfterGridDestroyed', true);
1071
+ }
1072
+ destroy(shouldEmptyDomElementContainer = false) {
1073
+ // dispose of all Services
1074
+ this.serviceList.forEach((service) => {
1075
+ if (service && service.dispose) {
1076
+ service.dispose();
1077
+ }
1078
+ });
1079
+ this.serviceList = [];
1080
+ // dispose all registered external resources
1081
+ if (Array.isArray(this._registeredResources)) {
1082
+ while (this._registeredResources.length > 0) {
1083
+ const resource = this._registeredResources.pop();
1084
+ if (resource?.dispose) {
1085
+ resource.dispose();
1086
+ }
1087
+ }
1088
+ this._registeredResources = [];
1089
+ }
1090
+ // dispose the Components
1091
+ this.slickEmptyWarning?.dispose();
1092
+ this.slickFooter?.dispose();
1093
+ this.slickPagination?.dispose();
1094
+ if (this._eventHandler?.unsubscribeAll) {
1095
+ this._eventHandler.unsubscribeAll();
1096
+ }
1097
+ this._eventPubSubService?.unsubscribeAll();
1098
+ if (this.dataView) {
1099
+ if (this.dataView?.setItems) {
1100
+ this.dataView.setItems([]);
1101
+ }
1102
+ if (this.dataView.destroy) {
1103
+ this.dataView.destroy();
1104
+ }
1105
+ }
1106
+ if (this.slickGrid?.destroy) {
1107
+ this.slickGrid.destroy(shouldEmptyDomElementContainer);
1108
+ }
1109
+ if (this.backendServiceApi) {
1110
+ for (const prop of Object.keys(this.backendServiceApi)) {
1111
+ delete this.backendServiceApi[prop];
1112
+ }
1113
+ this.backendServiceApi = undefined;
1114
+ }
1115
+ for (const prop of Object.keys(this.columnDefinitions)) {
1116
+ this.columnDefinitions[prop] = null;
1117
+ }
1118
+ for (const prop of Object.keys(this.sharedService)) {
1119
+ this.sharedService[prop] = null;
1120
+ }
1121
+ // we could optionally also empty the content of the grid container DOM element
1122
+ if (shouldEmptyDomElementContainer) {
1123
+ this.emptyGridContainerElm();
1124
+ }
1125
+ // also unsubscribe all RxJS subscriptions
1126
+ this.subscriptions = unsubscribeAll(this.subscriptions);
1127
+ this._dataset = null;
1128
+ this.datasetHierarchical = undefined;
1129
+ this._columnDefinitions = [];
1130
+ this._angularGridInstances = undefined;
1131
+ }
1132
+ emptyGridContainerElm() {
1133
+ const gridContainerId = this.gridOptions?.gridContainerId ?? 'grid1';
1134
+ const gridContainerElm = document.querySelector(`#${gridContainerId}`);
1135
+ emptyElement(gridContainerElm);
1136
+ }
1137
+ /**
1138
+ * Define our internal Post Process callback, it will execute internally after we get back result from the Process backend call
1139
+ * For now, this is GraphQL Service ONLY feature and it will basically refresh the Dataset & Pagination without having the user to create his own PostProcess every time
1140
+ */
1141
+ createBackendApiInternalPostProcessCallback(gridOptions) {
1142
+ const backendApi = gridOptions && gridOptions.backendServiceApi;
1143
+ if (backendApi && backendApi.service) {
1144
+ const backendApiService = backendApi.service;
1145
+ // internalPostProcess only works (for now) with a GraphQL Service, so make sure it is of that type
1146
+ if (typeof backendApiService.getDatasetName === 'function') {
1147
+ backendApi.internalPostProcess = (processResult) => {
1148
+ const datasetName = (backendApi && backendApiService && typeof backendApiService.getDatasetName === 'function') ? backendApiService.getDatasetName() : '';
1149
+ if (processResult?.data[datasetName]) {
1150
+ const data = processResult.data[datasetName].hasOwnProperty('nodes') ? processResult.data[datasetName].nodes : processResult.data[datasetName];
1151
+ const totalCount = processResult.data[datasetName].hasOwnProperty('totalCount') ? processResult.data[datasetName].totalCount : processResult.data[datasetName].length;
1152
+ this.refreshGridData(data, totalCount || 0);
1153
+ }
1154
+ };
1155
+ }
1156
+ }
1157
+ }
1158
+ initialization(eventHandler) {
1159
+ this.gridOptions.translater = this.translaterService;
1160
+ this._eventHandler = eventHandler;
1161
+ // when detecting a frozen grid, we'll automatically enable the mousewheel scroll handler so that we can scroll from both left/right frozen containers
1162
+ if (this.gridOptions && ((this.gridOptions.frozenRow !== undefined && this.gridOptions.frozenRow >= 0) || this.gridOptions.frozenColumn !== undefined && this.gridOptions.frozenColumn >= 0) && this.gridOptions.enableMouseWheelScrollHandler === undefined) {
1163
+ this.gridOptions.enableMouseWheelScrollHandler = true;
1164
+ }
1165
+ this._eventPubSubService.eventNamingStyle = this.gridOptions?.eventNamingStyle ?? EventNamingStyle.camelCase;
1166
+ this._eventPubSubService.publish('onBeforeGridCreate', true);
1167
+ // make sure the dataset is initialized (if not it will throw an error that it cannot getLength of null)
1168
+ this._dataset = this._dataset || [];
1169
+ this.gridOptions = this.mergeGridOptions(this.gridOptions);
1170
+ this._paginationOptions = this.gridOptions?.pagination;
1171
+ this.locales = this.gridOptions?.locales ?? Constants.locales;
1172
+ this.backendServiceApi = this.gridOptions?.backendServiceApi;
1173
+ this._isLocalGrid = !this.backendServiceApi; // considered a local grid if it doesn't have a backend service set
1174
+ this.createBackendApiInternalPostProcessCallback(this.gridOptions);
1175
+ if (!this.customDataView) {
1176
+ const dataviewInlineFilters = this.gridOptions.dataView && this.gridOptions.dataView.inlineFilters || false;
1177
+ let dataViewOptions = { inlineFilters: dataviewInlineFilters };
1178
+ if (this.gridOptions.draggableGrouping || this.gridOptions.enableGrouping) {
1179
+ this.groupItemMetadataProvider = new SlickGroupItemMetadataProvider();
1180
+ this.sharedService.groupItemMetadataProvider = this.groupItemMetadataProvider;
1181
+ dataViewOptions = { ...dataViewOptions, groupItemMetadataProvider: this.groupItemMetadataProvider };
1182
+ }
1183
+ this.dataView = new Slick.Data.DataView(dataViewOptions);
1184
+ this._eventPubSubService.publish('onDataviewCreated', this.dataView);
1185
+ }
1186
+ // get any possible Services that user want to register which don't require SlickGrid to be instantiated
1187
+ // RxJS Resource is in this lot because it has to be registered before anything else and doesn't require SlickGrid to be initialized
1188
+ this.preRegisterResources();
1189
+ // for convenience to the user, we provide the property "editor" as an Angular-Slickgrid editor complex object
1190
+ // however "editor" is used internally by SlickGrid for it's own Editor Factory
1191
+ // so in our lib we will swap "editor" and copy it into a new property called "internalColumnEditor"
1192
+ // then take back "editor.model" and make it the new "editor" so that SlickGrid Editor Factory still works
1193
+ this._columnDefinitions = this.swapInternalEditorToSlickGridFactoryEditor(this._columnDefinitions);
1194
+ // if the user wants to automatically add a Custom Editor Formatter, we need to call the auto add function again
1195
+ if (this.gridOptions.autoAddCustomEditorFormatter) {
1196
+ autoAddEditorFormatterToColumnsWithEditor(this._columnDefinitions, this.gridOptions.autoAddCustomEditorFormatter);
1197
+ }
1198
+ // save reference for all columns before they optionally become hidden/visible
1199
+ this.sharedService.allColumns = this._columnDefinitions;
1200
+ this.sharedService.visibleColumns = this._columnDefinitions;
1201
+ this.extensionService.createExtensionsBeforeGridCreation(this._columnDefinitions, this.gridOptions);
1202
+ // if user entered some Pinning/Frozen "presets", we need to apply them in the grid options
1203
+ if (this.gridOptions.presets?.pinning) {
1204
+ this.gridOptions = { ...this.gridOptions, ...this.gridOptions.presets.pinning };
1205
+ }
1206
+ // build SlickGrid Grid, also user might optionally pass a custom dataview (e.g. remote model)
1207
+ this.slickGrid = new Slick.Grid(`#${this.gridId}`, this.customDataView || this.dataView, this._columnDefinitions, this.gridOptions);
1208
+ this.sharedService.dataView = this.dataView;
1209
+ this.sharedService.slickGrid = this.slickGrid;
1210
+ this.sharedService.gridContainerElement = this.elm.nativeElement;
1211
+ this.extensionService.bindDifferentExtensions();
1212
+ this.bindDifferentHooks(this.slickGrid, this.gridOptions, this.dataView);
1213
+ // when it's a frozen grid, we need to keep the frozen column id for reference if we ever show/hide column from ColumnPicker/GridMenu afterward
1214
+ const frozenColumnIndex = this.gridOptions.frozenColumn !== undefined ? this.gridOptions.frozenColumn : -1;
1215
+ if (frozenColumnIndex >= 0 && frozenColumnIndex <= this._columnDefinitions.length) {
1216
+ this.sharedService.frozenVisibleColumnId = this._columnDefinitions[frozenColumnIndex].id || '';
1217
+ }
1218
+ // get any possible Services that user want to register
1219
+ this.registerResources();
1220
+ // initialize the SlickGrid grid
1221
+ this.slickGrid.init();
1222
+ // initialized the resizer service only after SlickGrid is initialized
1223
+ // if we don't we end up binding our resize to a grid element that doesn't yet exist in the DOM and the resizer service will fail silently (because it has a try/catch that unbinds the resize without throwing back)
1224
+ if (this.gridContainerElement) {
1225
+ this.resizerService.init(this.slickGrid, this.gridContainerElement);
1226
+ }
1227
+ // user could show a custom footer with the data metrics (dataset length and last updated timestamp)
1228
+ if (!this.gridOptions.enablePagination && this.gridOptions.showCustomFooter && this.gridOptions.customFooterOptions && this.gridContainerElement) {
1229
+ this.slickFooter = new SlickFooterComponent(this.slickGrid, this.gridOptions.customFooterOptions, this._eventPubSubService, this.translaterService);
1230
+ this.slickFooter.renderFooter(this.gridContainerElement);
1231
+ }
1232
+ if (!this.customDataView && this.dataView) {
1233
+ // load the data in the DataView (unless it's a hierarchical dataset, if so it will be loaded after the initial tree sort)
1234
+ const initialDataset = this.gridOptions?.enableTreeData ? this.sortTreeDataset(this._dataset) : this._dataset;
1235
+ this.dataView.beginUpdate();
1236
+ this.dataView.setItems(initialDataset || [], this.gridOptions.datasetIdPropertyName ?? 'id');
1237
+ this.dataView.endUpdate();
1238
+ // if you don't want the items that are not visible (due to being filtered out or being on a different page)
1239
+ // to stay selected, pass 'false' to the second arg
1240
+ const selectionModel = this.slickGrid?.getSelectionModel();
1241
+ if (selectionModel && this.gridOptions && this.gridOptions.dataView && this.gridOptions.dataView.hasOwnProperty('syncGridSelection')) {
1242
+ // if we are using a Backend Service, we will do an extra flag check, the reason is because it might have some unintended behaviors
1243
+ // with the BackendServiceApi because technically the data in the page changes the DataView on every page change.
1244
+ let preservedRowSelectionWithBackend = false;
1245
+ if (this.gridOptions.backendServiceApi && this.gridOptions.dataView.hasOwnProperty('syncGridSelectionWithBackendService')) {
1246
+ preservedRowSelectionWithBackend = this.gridOptions.dataView.syncGridSelectionWithBackendService;
1247
+ }
1248
+ const syncGridSelection = this.gridOptions.dataView.syncGridSelection;
1249
+ if (typeof syncGridSelection === 'boolean') {
1250
+ let preservedRowSelection = syncGridSelection;
1251
+ if (!this._isLocalGrid) {
1252
+ // when using BackendServiceApi, we'll be using the "syncGridSelectionWithBackendService" flag BUT "syncGridSelection" must also be set to True
1253
+ preservedRowSelection = syncGridSelection && preservedRowSelectionWithBackend;
1254
+ }
1255
+ this.dataView.syncGridSelection(this.slickGrid, preservedRowSelection);
1256
+ }
1257
+ else if (typeof syncGridSelection === 'object') {
1258
+ this.dataView.syncGridSelection(this.slickGrid, syncGridSelection.preserveHidden, syncGridSelection.preserveHiddenOnSelectionChange);
1259
+ }
1260
+ }
1261
+ const datasetLn = this.dataView.getLength() || this._dataset && this._dataset.length || 0;
1262
+ if (datasetLn > 0) {
1263
+ if (!this._isDatasetInitialized && (this.gridOptions.enableCheckboxSelector || this.gridOptions.enableRowSelection)) {
1264
+ this.loadRowSelectionPresetWhenExists();
1265
+ }
1266
+ this.loadFilterPresetsWhenDatasetInitialized();
1267
+ this._isDatasetInitialized = true;
1268
+ }
1269
+ }
1270
+ // user might want to hide the header row on page load but still have `enableFiltering: true`
1271
+ // if that is the case, we need to hide the headerRow ONLY AFTER all filters got created & dataView exist
1272
+ if (this._hideHeaderRowAfterPageLoad) {
1273
+ this.showHeaderRow(false);
1274
+ this.sharedService.hideHeaderRowAfterPageLoad = this._hideHeaderRowAfterPageLoad;
1275
+ }
1276
+ // publish & dispatch certain events
1277
+ this._eventPubSubService.publish('onGridCreated', this.slickGrid);
1278
+ // after the DataView is created & updated execute some processes
1279
+ if (!this.customDataView) {
1280
+ this.executeAfterDataviewCreated(this.slickGrid, this.gridOptions);
1281
+ }
1282
+ // bind resize ONLY after the dataView is ready
1283
+ this.bindResizeHook(this.slickGrid, this.gridOptions);
1284
+ // bind the Backend Service API callback functions only after the grid is initialized
1285
+ // because the preProcess() and onInit() might get triggered
1286
+ if (this.gridOptions?.backendServiceApi) {
1287
+ this.bindBackendCallbackFunctions(this.gridOptions);
1288
+ }
1289
+ // local grid, check if we need to show the Pagination
1290
+ // if so then also check if there's any presets and finally initialize the PaginationService
1291
+ // a local grid with Pagination presets will potentially have a different total of items, we'll need to get it from the DataView and update our total
1292
+ if (this.gridOptions?.enablePagination && this._isLocalGrid) {
1293
+ this.showPagination = true;
1294
+ this.loadLocalGridPagination(this.dataset);
1295
+ }
1296
+ this._angularGridInstances = {
1297
+ // Slick Grid & DataView objects
1298
+ dataView: this.dataView,
1299
+ slickGrid: this.slickGrid,
1300
+ extensions: this.extensionService?.extensionList,
1301
+ // public methods
1302
+ destroy: this.destroy.bind(this),
1303
+ // return all available Services (non-singleton)
1304
+ backendService: this.gridOptions?.backendServiceApi?.service,
1305
+ filterService: this.filterService,
1306
+ gridEventService: this.gridEventService,
1307
+ gridStateService: this.gridStateService,
1308
+ gridService: this.gridService,
1309
+ groupingService: this.groupingService,
1310
+ extensionService: this.extensionService,
1311
+ paginationService: this.paginationService,
1312
+ resizerService: this.resizerService,
1313
+ sortService: this.sortService,
1314
+ treeDataService: this.treeDataService,
1315
+ };
1316
+ // all instances (SlickGrid, DataView & all Services)
1317
+ this._eventPubSubService.publish('onAngularGridCreated', this._angularGridInstances);
1318
+ }
1319
+ /**
1320
+ * On a Pagination changed, we will trigger a Grid State changed with the new pagination info
1321
+ * Also if we use Row Selection or the Checkbox Selector, we need to reset any selection
1322
+ */
1323
+ paginationChanged(pagination) {
1324
+ const isSyncGridSelectionEnabled = this.gridStateService?.needToPreserveRowSelection() ?? false;
1325
+ if (!isSyncGridSelectionEnabled && (this.gridOptions.enableRowSelection || this.gridOptions.enableCheckboxSelector)) {
1326
+ this.slickGrid.setSelectedRows([]);
1327
+ }
1328
+ const { pageNumber, pageSize } = pagination;
1329
+ if (this.sharedService) {
1330
+ if (pageSize !== undefined && pageNumber !== undefined) {
1331
+ this.sharedService.currentPagination = { pageNumber, pageSize };
1332
+ }
1333
+ }
1334
+ this._eventPubSubService.publish('onGridStateChanged', {
1335
+ change: { newValues: { pageNumber, pageSize }, type: GridStateType.pagination },
1336
+ gridState: this.gridStateService.getCurrentGridState()
1337
+ });
1338
+ this.cd.markForCheck();
1339
+ }
1340
+ /**
1341
+ * When dataset changes, we need to refresh the entire grid UI & possibly resize it as well
1342
+ * @param dataset
1343
+ */
1344
+ refreshGridData(dataset, totalCount) {
1345
+ if (this.gridOptions && this.gridOptions.enableEmptyDataWarningMessage && Array.isArray(dataset)) {
1346
+ const finalTotalCount = totalCount || dataset.length;
1347
+ this.displayEmptyDataWarning(finalTotalCount < 1);
1348
+ }
1349
+ if (Array.isArray(dataset) && this.slickGrid && this.dataView?.setItems) {
1350
+ this.dataView.setItems(dataset, this.gridOptions.datasetIdPropertyName ?? 'id');
1351
+ if (!this.gridOptions.backendServiceApi && !this.gridOptions.enableTreeData) {
1352
+ this.dataView.reSort();
1353
+ }
1354
+ if (dataset.length > 0) {
1355
+ if (!this._isDatasetInitialized) {
1356
+ this.loadFilterPresetsWhenDatasetInitialized();
1357
+ if (this.gridOptions.enableCheckboxSelector) {
1358
+ this.loadRowSelectionPresetWhenExists();
1359
+ }
1360
+ }
1361
+ this._isDatasetInitialized = true;
1362
+ }
1363
+ if (dataset) {
1364
+ this.slickGrid.invalidate();
1365
+ }
1366
+ // display the Pagination component only after calling this refresh data first, we call it here so that if we preset pagination page number it will be shown correctly
1367
+ this.showPagination = (this.gridOptions && (this.gridOptions.enablePagination || (this.gridOptions.backendServiceApi && this.gridOptions.enablePagination === undefined))) ? true : false;
1368
+ if (this._paginationOptions && this.gridOptions?.pagination && this.gridOptions?.backendServiceApi) {
1369
+ const paginationOptions = this.setPaginationOptionsWhenPresetDefined(this.gridOptions, this._paginationOptions);
1370
+ // when we have a totalCount use it, else we'll take it from the pagination object
1371
+ // only update the total items if it's different to avoid refreshing the UI
1372
+ const totalRecords = (totalCount !== undefined) ? totalCount : (this.gridOptions?.pagination?.totalItems);
1373
+ if (totalRecords !== undefined && totalRecords !== this.totalItems) {
1374
+ this.totalItems = +totalRecords;
1375
+ }
1376
+ // initialize the Pagination Service with new pagination options (which might have presets)
1377
+ if (!this._isPaginationInitialized) {
1378
+ this.initializePaginationService(paginationOptions);
1379
+ }
1380
+ else {
1381
+ // update the pagination service with the new total
1382
+ this.paginationService.updateTotalItems(this.totalItems);
1383
+ }
1384
+ }
1385
+ // resize the grid inside a slight timeout, in case other DOM element changed prior to the resize (like a filter/pagination changed)
1386
+ if (this.slickGrid && this.gridOptions.enableAutoResize) {
1387
+ const delay = this.gridOptions.autoResize && this.gridOptions.autoResize.delay;
1388
+ this.resizerService.resizeGrid(delay || 10);
1389
+ }
1390
+ }
1391
+ }
1392
+ /**
1393
+ * Check if there's any Pagination Presets defined in the Grid Options,
1394
+ * if there are then load them in the paginationOptions object
1395
+ */
1396
+ setPaginationOptionsWhenPresetDefined(gridOptions, paginationOptions) {
1397
+ if (gridOptions.presets?.pagination && paginationOptions && !this._isPaginationInitialized) {
1398
+ paginationOptions.pageSize = gridOptions.presets.pagination.pageSize;
1399
+ paginationOptions.pageNumber = gridOptions.presets.pagination.pageNumber;
1400
+ }
1401
+ return paginationOptions;
1402
+ }
1403
+ /**
1404
+ * Dynamically change or update the column definitions list.
1405
+ * We will re-render the grid so that the new header and data shows up correctly.
1406
+ * If using i18n, we also need to trigger a re-translate of the column headers
1407
+ */
1408
+ updateColumnDefinitionsList(newColumnDefinitions) {
1409
+ // map/swap the internal library Editor to the SlickGrid Editor factory
1410
+ newColumnDefinitions = this.swapInternalEditorToSlickGridFactoryEditor(newColumnDefinitions);
1411
+ if (this.gridOptions.enableTranslate) {
1412
+ this.extensionService.translateColumnHeaders(false, newColumnDefinitions);
1413
+ }
1414
+ else {
1415
+ this.extensionService.renderColumnHeaders(newColumnDefinitions, true);
1416
+ }
1417
+ if (this.gridOptions?.enableAutoSizeColumns) {
1418
+ this.slickGrid.autosizeColumns();
1419
+ }
1420
+ else if (this.gridOptions?.enableAutoResizeColumnsByCellContent && this.resizerService?.resizeColumnsByCellContent) {
1421
+ this.resizerService.resizeColumnsByCellContent();
1422
+ }
1423
+ }
1424
+ /**
1425
+ * Show the filter row displayed on first row, we can optionally pass false to hide it.
1426
+ * @param showing
1427
+ */
1428
+ showHeaderRow(showing = true) {
1429
+ this.slickGrid.setHeaderRowVisibility(showing, false);
1430
+ if (showing === true && this._isGridInitialized) {
1431
+ this.slickGrid.setColumns(this.columnDefinitions);
1432
+ }
1433
+ return showing;
1434
+ }
1435
+ //
1436
+ // private functions
1437
+ // ------------------
1438
+ /**
1439
+ * Loop through all column definitions and copy the original optional `width` properties optionally provided by the user.
1440
+ * We will use this when doing a resize by cell content, if user provided a `width` it won't override it.
1441
+ */
1442
+ copyColumnWidthsReference(columnDefinitions) {
1443
+ columnDefinitions.forEach(col => col.originalWidth = col.width);
1444
+ }
1445
+ displayEmptyDataWarning(showWarning = true) {
1446
+ this.slickEmptyWarning?.showEmptyDataMessage(showWarning);
1447
+ }
1448
+ bindDifferentHooks(grid, gridOptions, dataView) {
1449
+ // on locale change, we have to manually translate the Headers, GridMenu
1450
+ if (this.translate?.onLangChange) {
1451
+ // translate some of them on first load, then on each language change
1452
+ if (gridOptions.enableTranslate) {
1453
+ this.extensionService.translateAllExtensions();
1454
+ this.translateColumnHeaderTitleKeys();
1455
+ this.translateColumnGroupKeys();
1456
+ }
1457
+ this.subscriptions.push(this.translate.onLangChange.subscribe(() => {
1458
+ // publish event of the same name that Slickgrid-Universal uses on a language change event
1459
+ this._eventPubSubService.publish('onLanguageChange');
1460
+ if (gridOptions.enableTranslate) {
1461
+ this.extensionService.translateAllExtensions();
1462
+ this.translateColumnHeaderTitleKeys();
1463
+ this.translateColumnGroupKeys();
1464
+ if (gridOptions.createPreHeaderPanel && !gridOptions.enableDraggableGrouping) {
1465
+ this.groupingService.translateGroupingAndColSpan();
1466
+ }
1467
+ }
1468
+ }));
1469
+ }
1470
+ // if user set an onInit Backend, we'll run it right away (and if so, we also need to run preProcess, internalPostProcess & postProcess)
1471
+ if (gridOptions.backendServiceApi) {
1472
+ const backendApi = gridOptions.backendServiceApi;
1473
+ if (backendApi?.service?.init) {
1474
+ backendApi.service.init(backendApi.options, gridOptions.pagination, this.slickGrid, this.sharedService);
1475
+ }
1476
+ }
1477
+ if (dataView && grid) {
1478
+ const slickgridEventPrefix = this.gridOptions?.defaultSlickgridEventPrefix ?? '';
1479
+ // expose all Slick Grid Events through dispatch
1480
+ for (const prop in grid) {
1481
+ if (grid.hasOwnProperty(prop) && prop.startsWith('on')) {
1482
+ const gridEventName = this._eventPubSubService.getEventNameByNamingConvention(prop, slickgridEventPrefix);
1483
+ this._eventHandler.subscribe(grid[prop], (event, args) => {
1484
+ return this._eventPubSubService.dispatchCustomEvent(gridEventName, { eventData: event, args });
1485
+ });
1486
+ }
1487
+ }
1488
+ // expose all Slick DataView Events through dispatch
1489
+ for (const prop in dataView) {
1490
+ if (dataView.hasOwnProperty(prop) && prop.startsWith('on')) {
1491
+ this._eventHandler.subscribe(dataView[prop], (event, args) => {
1492
+ const dataViewEventName = this._eventPubSubService.getEventNameByNamingConvention(prop, slickgridEventPrefix);
1493
+ return this._eventPubSubService.dispatchCustomEvent(dataViewEventName, { eventData: event, args });
1494
+ });
1495
+ }
1496
+ }
1497
+ // on cell click, mainly used with the columnDef.action callback
1498
+ this.gridEventService.bindOnCellChange(grid);
1499
+ this.gridEventService.bindOnClick(grid);
1500
+ if (dataView && grid) {
1501
+ // bind external sorting (backend) when available or default onSort (dataView)
1502
+ if (gridOptions.enableSorting) {
1503
+ // bind external sorting (backend) unless specified to use the local one
1504
+ if (gridOptions.backendServiceApi && !gridOptions.backendServiceApi.useLocalSorting) {
1505
+ this.sortService.bindBackendOnSort(grid);
1506
+ }
1507
+ else {
1508
+ this.sortService.bindLocalOnSort(grid);
1509
+ }
1510
+ }
1511
+ // bind external filter (backend) when available or default onFilter (dataView)
1512
+ if (gridOptions.enableFiltering) {
1513
+ this.filterService.init(grid);
1514
+ // bind external filter (backend) unless specified to use the local one
1515
+ if (gridOptions.backendServiceApi && !gridOptions.backendServiceApi.useLocalFiltering) {
1516
+ this.filterService.bindBackendOnFilter(grid);
1517
+ }
1518
+ else {
1519
+ this.filterService.bindLocalOnFilter(grid);
1520
+ }
1521
+ }
1522
+ // load any presets if any (after dataset is initialized)
1523
+ this.loadColumnPresetsWhenDatasetInitialized();
1524
+ this.loadFilterPresetsWhenDatasetInitialized();
1525
+ // When data changes in the DataView, we need to refresh the metrics and/or display a warning if the dataset is empty
1526
+ this._eventHandler.subscribe(dataView.onRowCountChanged, () => {
1527
+ grid.invalidate();
1528
+ this.handleOnItemCountChanged(this.dataView.getFilteredItemCount() || 0, dataView.getItemCount());
1529
+ });
1530
+ this._eventHandler.subscribe(dataView.onSetItemsCalled, (_e, args) => {
1531
+ grid.invalidate();
1532
+ this.handleOnItemCountChanged(this.dataView.getFilteredItemCount(), args.itemCount);
1533
+ // when user has resize by content enabled, we'll force a full width calculation since we change our entire dataset
1534
+ if (args.itemCount > 0 && (this.gridOptions.autosizeColumnsByCellContentOnFirstLoad || this.gridOptions.enableAutoResizeColumnsByCellContent)) {
1535
+ this.resizerService.resizeColumnsByCellContent(!this.gridOptions?.resizeByContentOnlyOnFirstLoad);
1536
+ }
1537
+ });
1538
+ this._eventHandler.subscribe(dataView.onRowsChanged, (_e, args) => {
1539
+ // filtering data with local dataset will not always show correctly unless we call this updateRow/render
1540
+ // also don't use "invalidateRows" since it destroys the entire row and as bad user experience when updating a row
1541
+ // see commit: https://github.com/ghiscoding/aurelia-slickgrid/commit/8c503a4d45fba11cbd8d8cc467fae8d177cc4f60
1542
+ if (gridOptions && gridOptions.enableFiltering && !gridOptions.enableRowDetailView) {
1543
+ if (args?.rows && Array.isArray(args.rows)) {
1544
+ args.rows.forEach((row) => grid.updateRow(row));
1545
+ grid.render();
1546
+ }
1547
+ }
1548
+ });
1549
+ }
1550
+ }
1551
+ // did the user add a colspan callback? If so, hook it into the DataView getItemMetadata
1552
+ if (gridOptions && gridOptions.colspanCallback && dataView && dataView.getItem && dataView.getItemMetadata) {
1553
+ dataView.getItemMetadata = (rowNumber) => {
1554
+ let callbackResult = null;
1555
+ if (gridOptions.colspanCallback && gridOptions.colspanCallback) {
1556
+ callbackResult = gridOptions.colspanCallback(dataView.getItem(rowNumber));
1557
+ }
1558
+ return callbackResult;
1559
+ };
1560
+ }
1561
+ }
1562
+ bindBackendCallbackFunctions(gridOptions) {
1563
+ const backendApi = gridOptions.backendServiceApi;
1564
+ const backendApiService = backendApi && backendApi.service;
1565
+ const serviceOptions = backendApiService?.options ?? {};
1566
+ const isExecuteCommandOnInit = (!serviceOptions) ? false : ((serviceOptions && serviceOptions.hasOwnProperty('executeProcessCommandOnInit')) ? serviceOptions['executeProcessCommandOnInit'] : true);
1567
+ if (backendApiService) {
1568
+ // update backend filters (if need be) BEFORE the query runs (via the onInit command a few lines below)
1569
+ // if user entered some any "presets", we need to reflect them all in the grid
1570
+ if (gridOptions && gridOptions.presets) {
1571
+ // Filters "presets"
1572
+ if (backendApiService.updateFilters && Array.isArray(gridOptions.presets.filters) && gridOptions.presets.filters.length > 0) {
1573
+ backendApiService.updateFilters(gridOptions.presets.filters, true);
1574
+ }
1575
+ // Sorters "presets"
1576
+ if (backendApiService.updateSorters && Array.isArray(gridOptions.presets.sorters) && gridOptions.presets.sorters.length > 0) {
1577
+ // when using multi-column sort, we can have multiple but on single sort then only grab the first sort provided
1578
+ const sortColumns = this.gridOptions.multiColumnSort ? gridOptions.presets.sorters : gridOptions.presets.sorters.slice(0, 1);
1579
+ backendApiService.updateSorters(undefined, sortColumns);
1580
+ }
1581
+ // Pagination "presets"
1582
+ if (backendApiService.updatePagination && gridOptions.presets.pagination) {
1583
+ const { pageNumber, pageSize } = gridOptions.presets.pagination;
1584
+ backendApiService.updatePagination(pageNumber, pageSize);
1585
+ }
1586
+ }
1587
+ else {
1588
+ const columnFilters = this.filterService.getColumnFilters();
1589
+ if (columnFilters && backendApiService.updateFilters) {
1590
+ backendApiService.updateFilters(columnFilters, false);
1591
+ }
1592
+ }
1593
+ // execute onInit command when necessary
1594
+ if (backendApi && backendApiService && (backendApi.onInit || isExecuteCommandOnInit)) {
1595
+ const query = (typeof backendApiService.buildQuery === 'function') ? backendApiService.buildQuery() : '';
1596
+ const process = (isExecuteCommandOnInit) ? (backendApi.process && backendApi.process(query) || null) : (backendApi.onInit && backendApi.onInit(query) || null);
1597
+ // wrap this inside a setTimeout to avoid timing issue since the gridOptions needs to be ready before running this onInit
1598
+ setTimeout(() => {
1599
+ const backendUtilityService = this.backendUtilityService;
1600
+ // keep start time & end timestamps & return it after process execution
1601
+ const startTime = new Date();
1602
+ // run any pre-process, if defined, for example a spinner
1603
+ if (backendApi.preProcess) {
1604
+ backendApi.preProcess();
1605
+ }
1606
+ // the processes can be a Promise (like Http)
1607
+ const totalItems = this.gridOptions?.pagination?.totalItems ?? 0;
1608
+ if (process instanceof Promise) {
1609
+ process
1610
+ .then((processResult) => backendUtilityService.executeBackendProcessesCallback(startTime, processResult, backendApi, totalItems))
1611
+ .catch((error) => backendUtilityService.onBackendError(error, backendApi));
1612
+ }
1613
+ else if (process && this.rxjs?.isObservable(process)) {
1614
+ this.subscriptions.push(process.subscribe({
1615
+ next: (processResult) => backendUtilityService.executeBackendProcessesCallback(startTime, processResult, backendApi, totalItems),
1616
+ error: (error) => backendUtilityService.onBackendError(error, backendApi)
1617
+ }));
1618
+ }
1619
+ });
1620
+ }
1621
+ }
1622
+ }
1623
+ bindResizeHook(grid, options) {
1624
+ if ((options.autoFitColumnsOnFirstLoad && options.autosizeColumnsByCellContentOnFirstLoad) || (options.enableAutoSizeColumns && options.enableAutoResizeColumnsByCellContent)) {
1625
+ throw new Error(`[Angular-Slickgrid] You cannot enable both autosize/fit viewport & resize by content, you must choose which resize technique to use. You can enable these 2 options ("autoFitColumnsOnFirstLoad" and "enableAutoSizeColumns") OR these other 2 options ("autosizeColumnsByCellContentOnFirstLoad" and "enableAutoResizeColumnsByCellContent").`);
1626
+ }
1627
+ // expand/autofit columns on first page load
1628
+ if (grid && options.autoFitColumnsOnFirstLoad && options.enableAutoSizeColumns) {
1629
+ grid.autosizeColumns();
1630
+ }
1631
+ // auto-resize grid on browser resize
1632
+ if (options.gridHeight || options.gridWidth) {
1633
+ this.resizerService.resizeGrid(0, { height: options.gridHeight, width: options.gridWidth });
1634
+ }
1635
+ else {
1636
+ this.resizerService.resizeGrid();
1637
+ }
1638
+ if (options.enableAutoResize) {
1639
+ if (grid && options.autoFitColumnsOnFirstLoad && options.enableAutoSizeColumns) {
1640
+ grid.autosizeColumns();
1641
+ }
1642
+ }
1643
+ }
1644
+ executeAfterDataviewCreated(_grid, gridOptions) {
1645
+ // if user entered some Sort "presets", we need to reflect them all in the DOM
1646
+ if (gridOptions.enableSorting) {
1647
+ if (gridOptions.presets && Array.isArray(gridOptions.presets.sorters)) {
1648
+ // when using multi-column sort, we can have multiple but on single sort then only grab the first sort provided
1649
+ const sortColumns = this.gridOptions.multiColumnSort ? gridOptions.presets.sorters : gridOptions.presets.sorters.slice(0, 1);
1650
+ this.sortService.loadGridSorters(sortColumns);
1651
+ }
1652
+ }
1653
+ }
1654
+ /** When data changes in the DataView, we'll refresh the metrics and/or display a warning if the dataset is empty */
1655
+ handleOnItemCountChanged(currentPageRowItemCount, totalItemCount) {
1656
+ this._currentDatasetLength = totalItemCount;
1657
+ this.metrics = {
1658
+ startTime: new Date(),
1659
+ endTime: new Date(),
1660
+ itemCount: currentPageRowItemCount,
1661
+ totalItemCount
1662
+ };
1663
+ // if custom footer is enabled, then we'll update its metrics
1664
+ if (this.slickFooter) {
1665
+ this.slickFooter.metrics = this.metrics;
1666
+ }
1667
+ // when using local (in-memory) dataset, we'll display a warning message when filtered data is empty
1668
+ if (this._isLocalGrid && this.gridOptions?.enableEmptyDataWarningMessage) {
1669
+ this.displayEmptyDataWarning(currentPageRowItemCount === 0);
1670
+ }
1671
+ }
1672
+ initializePaginationService(paginationOptions) {
1673
+ if (this.gridOptions) {
1674
+ this.paginationData = {
1675
+ gridOptions: this.gridOptions,
1676
+ paginationService: this.paginationService,
1677
+ };
1678
+ this.paginationService.totalItems = this.totalItems;
1679
+ this.paginationService.init(this.slickGrid, paginationOptions, this.backendServiceApi);
1680
+ this.subscriptions.push(this._eventPubSubService.subscribe('onPaginationChanged', (paginationChanges) => {
1681
+ this.paginationChanged(paginationChanges);
1682
+ }), this._eventPubSubService.subscribe('onPaginationVisibilityChanged', (visibility) => {
1683
+ this.showPagination = visibility?.visible ?? false;
1684
+ if (this.gridOptions?.backendServiceApi) {
1685
+ this.backendUtilityService?.refreshBackendDataset(this.gridOptions);
1686
+ }
1687
+ this.renderPagination(this.showPagination);
1688
+ }));
1689
+ // also initialize (render) the pagination component
1690
+ this.renderPagination();
1691
+ this._isPaginationInitialized = true;
1692
+ }
1693
+ this.cd.detectChanges();
1694
+ }
1695
+ /** Load the Editor Collection asynchronously and replace the "collection" property when Observable resolves */
1696
+ loadEditorCollectionAsync(column) {
1697
+ const collectionAsync = column && column.editor && column.editor.collectionAsync;
1698
+ if (collectionAsync instanceof Observable) {
1699
+ this.subscriptions.push(collectionAsync.subscribe((resolvedCollection) => this.updateEditorCollection(column, resolvedCollection)));
1700
+ }
1701
+ else if (collectionAsync instanceof Promise) {
1702
+ // wait for the "collectionAsync", once resolved we will save it into the "collection"
1703
+ // the collectionAsync can be of 3 types HttpClient, HttpFetch or a Promise
1704
+ collectionAsync.then((response) => {
1705
+ if (Array.isArray(response)) {
1706
+ this.updateEditorCollection(column, response); // from Promise
1707
+ }
1708
+ });
1709
+ }
1710
+ }
1711
+ /** Load any possible Columns Grid Presets */
1712
+ loadColumnPresetsWhenDatasetInitialized() {
1713
+ // if user entered some Columns "presets", we need to reflect them all in the grid
1714
+ if (this.gridOptions.presets && Array.isArray(this.gridOptions.presets.columns) && this.gridOptions.presets.columns.length > 0) {
1715
+ const gridColumns = this.gridStateService.getAssociatedGridColumns(this.slickGrid, this.gridOptions.presets.columns);
1716
+ if (gridColumns && Array.isArray(gridColumns) && gridColumns.length > 0) {
1717
+ // make sure that the checkbox selector is also visible if it is enabled
1718
+ if (this.gridOptions.enableCheckboxSelector) {
1719
+ const checkboxColumn = (Array.isArray(this._columnDefinitions) && this._columnDefinitions.length > 0) ? this._columnDefinitions[0] : null;
1720
+ if (checkboxColumn && checkboxColumn.id === '_checkbox_selector' && gridColumns[0].id !== '_checkbox_selector') {
1721
+ gridColumns.unshift(checkboxColumn);
1722
+ }
1723
+ }
1724
+ // keep copy the original optional `width` properties optionally provided by the user.
1725
+ // We will use this when doing a resize by cell content, if user provided a `width` it won't override it.
1726
+ gridColumns.forEach(col => col.originalWidth = col.width);
1727
+ // finally set the new presets columns (including checkbox selector if need be)
1728
+ this.slickGrid.setColumns(gridColumns);
1729
+ this.sharedService.visibleColumns = gridColumns;
1730
+ }
1731
+ }
1732
+ }
1733
+ /** Load any possible Filters Grid Presets */
1734
+ loadFilterPresetsWhenDatasetInitialized() {
1735
+ if (this.gridOptions && !this.customDataView) {
1736
+ // if user entered some Filter "presets", we need to reflect them all in the DOM
1737
+ // also note that a presets of Tree Data Toggling will also call this method because Tree Data toggling does work with data filtering
1738
+ // (collapsing a parent will basically use Filter for hidding (aka collapsing) away the child underneat it)
1739
+ if (this.gridOptions.presets && (Array.isArray(this.gridOptions.presets.filters) || Array.isArray(this.gridOptions.presets?.treeData?.toggledItems))) {
1740
+ this.filterService.populateColumnFilterSearchTermPresets(this.gridOptions.presets?.filters || []);
1741
+ }
1742
+ }
1743
+ }
1744
+ /**
1745
+ * local grid, check if we need to show the Pagination
1746
+ * if so then also check if there's any presets and finally initialize the PaginationService
1747
+ * a local grid with Pagination presets will potentially have a different total of items, we'll need to get it from the DataView and update our total
1748
+ */
1749
+ loadLocalGridPagination(dataset) {
1750
+ if (this.gridOptions && this._paginationOptions) {
1751
+ this.totalItems = Array.isArray(dataset) ? dataset.length : 0;
1752
+ if (this._paginationOptions && this.dataView?.getPagingInfo) {
1753
+ const slickPagingInfo = this.dataView.getPagingInfo();
1754
+ if (slickPagingInfo?.hasOwnProperty('totalRows') && this._paginationOptions.totalItems !== slickPagingInfo.totalRows) {
1755
+ this.totalItems = slickPagingInfo.totalRows || 0;
1756
+ }
1757
+ }
1758
+ this._paginationOptions.totalItems = this.totalItems;
1759
+ const paginationOptions = this.setPaginationOptionsWhenPresetDefined(this.gridOptions, this._paginationOptions);
1760
+ this.initializePaginationService(paginationOptions);
1761
+ }
1762
+ }
1763
+ /** Load any Row Selections into the DataView that were presets by the user */
1764
+ loadRowSelectionPresetWhenExists() {
1765
+ // if user entered some Row Selections "presets"
1766
+ const presets = this.gridOptions?.presets;
1767
+ const selectionModel = this.slickGrid?.getSelectionModel();
1768
+ const enableRowSelection = this.gridOptions && (this.gridOptions.enableCheckboxSelector || this.gridOptions.enableRowSelection);
1769
+ if (enableRowSelection && selectionModel && presets && presets.rowSelection && (Array.isArray(presets.rowSelection.gridRowIndexes) || Array.isArray(presets.rowSelection.dataContextIds))) {
1770
+ let dataContextIds = presets.rowSelection.dataContextIds;
1771
+ let gridRowIndexes = presets.rowSelection.gridRowIndexes;
1772
+ // maps the IDs to the Grid Rows and vice versa, the "dataContextIds" has precedence over the other
1773
+ if (Array.isArray(dataContextIds) && dataContextIds.length > 0) {
1774
+ gridRowIndexes = this.dataView.mapIdsToRows(dataContextIds) || [];
1775
+ }
1776
+ else if (Array.isArray(gridRowIndexes) && gridRowIndexes.length > 0) {
1777
+ dataContextIds = this.dataView.mapRowsToIds(gridRowIndexes) || [];
1778
+ }
1779
+ this.gridStateService.selectedRowDataContextIds = dataContextIds;
1780
+ // change the selected rows except UNLESS it's a Local Grid with Pagination
1781
+ // local Pagination uses the DataView and that also trigger a change/refresh
1782
+ // and we don't want to trigger 2 Grid State changes just 1
1783
+ if ((this._isLocalGrid && !this.gridOptions.enablePagination) || !this._isLocalGrid) {
1784
+ setTimeout(() => {
1785
+ if (this.slickGrid && Array.isArray(gridRowIndexes)) {
1786
+ this.slickGrid.setSelectedRows(gridRowIndexes);
1787
+ }
1788
+ });
1789
+ }
1790
+ }
1791
+ }
1792
+ mergeGridOptions(gridOptions) {
1793
+ gridOptions.gridId = this.gridId;
1794
+ gridOptions.gridContainerId = `slickGridContainer-${this.gridId}`;
1795
+ // if we have a backendServiceApi and the enablePagination is undefined, we'll assume that we do want to see it, else get that defined value
1796
+ gridOptions.enablePagination = ((gridOptions.backendServiceApi && gridOptions.enablePagination === undefined) ? true : gridOptions.enablePagination) || false;
1797
+ // use jquery extend to deep merge & copy to avoid immutable properties being changed in GlobalGridOptions after a route change
1798
+ const options = $.extend(true, {}, GlobalGridOptions, this.forRootConfig, gridOptions);
1799
+ // using jQuery extend to do a deep clone has an unwanted side on objects and pageSizes but ES6 spread has other worst side effects
1800
+ // so we will just overwrite the pageSizes when needed, this is the only one causing issues so far.
1801
+ // jQuery wrote this on their docs:: On a deep extend, Object and Array are extended, but object wrappers on primitive types such as String, Boolean, and Number are not.
1802
+ if (options?.pagination && (gridOptions.enablePagination || gridOptions.backendServiceApi) && (this.forRootConfig.pagination || gridOptions.pagination)) {
1803
+ options.pagination.pageSize = gridOptions.pagination?.pageSize ?? this.forRootConfig.pagination?.pageSize ?? GlobalGridOptions.pagination.pageSize;
1804
+ options.pagination.pageSizes = gridOptions.pagination?.pageSizes ?? this.forRootConfig.pagination?.pageSizes ?? GlobalGridOptions.pagination.pageSizes;
1805
+ }
1806
+ // also make sure to show the header row if user have enabled filtering
1807
+ this._hideHeaderRowAfterPageLoad = (options.showHeaderRow === false);
1808
+ if (options.enableFiltering && !options.showHeaderRow) {
1809
+ options.showHeaderRow = options.enableFiltering;
1810
+ }
1811
+ // when we use Pagination on Local Grid, it doesn't seem to work without enableFiltering
1812
+ // so we'll enable the filtering but we'll keep the header row hidden
1813
+ if (options && !options.enableFiltering && options.enablePagination && this._isLocalGrid) {
1814
+ options.enableFiltering = true;
1815
+ options.showHeaderRow = false;
1816
+ this._hideHeaderRowAfterPageLoad = true;
1817
+ if (this.sharedService) {
1818
+ this.sharedService.hideHeaderRowAfterPageLoad = true;
1819
+ }
1820
+ }
1821
+ return options;
1822
+ }
1823
+ /** Pre-Register any Resource that don't require SlickGrid to be instantiated (for example RxJS Resource) */
1824
+ preRegisterResources() {
1825
+ this._registeredResources = this.gridOptions.registerExternalResources || [];
1826
+ // Angular-Slickgrid requires RxJS, so we'll register it as the first resource
1827
+ this.registerRxJsResource(new RxJsResource());
1828
+ }
1829
+ registerResources() {
1830
+ // at this point, we consider all the registered services as external services, anything else registered afterward aren't external
1831
+ if (Array.isArray(this._registeredResources)) {
1832
+ this.sharedService.externalRegisteredResources = this._registeredResources;
1833
+ }
1834
+ // push all other Services that we want to be registered
1835
+ this._registeredResources.push(this.gridService, this.gridStateService);
1836
+ // when using Grouping/DraggableGrouping/Colspan register its Service
1837
+ if (this.gridOptions.createPreHeaderPanel && !this.gridOptions.enableDraggableGrouping) {
1838
+ this._registeredResources.push(this.groupingService);
1839
+ }
1840
+ // when using Tree Data View, register its Service
1841
+ if (this.gridOptions.enableTreeData) {
1842
+ this._registeredResources.push(this.treeDataService);
1843
+ }
1844
+ // when user enables translation, we need to translate Headers on first pass & subsequently in the bindDifferentHooks
1845
+ if (this.gridOptions.enableTranslate) {
1846
+ this.extensionService.translateColumnHeaders();
1847
+ }
1848
+ if (this.gridOptions.enableRowDetailView) {
1849
+ this.slickRowDetailView = new SlickRowDetailView(this.angularUtilService, this.appRef, this._eventPubSubService, this.elm.nativeElement, this.rxjs);
1850
+ this.slickRowDetailView.create(this.columnDefinitions, this.gridOptions);
1851
+ this._registeredResources.push(this.slickRowDetailView);
1852
+ this.extensionService.addExtensionToList(ExtensionName.rowDetailView, { name: ExtensionName.rowDetailView, instance: this.slickRowDetailView });
1853
+ }
1854
+ // also initialize (render) the empty warning component
1855
+ this.slickEmptyWarning = new SlickEmptyWarningComponent();
1856
+ this._registeredResources.push(this.slickEmptyWarning);
1857
+ // bind & initialize all Components/Services that were tagged as enabled
1858
+ // register all services by executing their init method and providing them with the Grid object
1859
+ if (Array.isArray(this._registeredResources)) {
1860
+ for (const resource of this._registeredResources) {
1861
+ if (typeof resource.init === 'function') {
1862
+ resource.init(this.slickGrid, this.containerService);
1863
+ }
1864
+ }
1865
+ }
1866
+ }
1867
+ /** Register the RxJS Resource in all necessary services which uses */
1868
+ registerRxJsResource(resource) {
1869
+ this.rxjs = resource;
1870
+ this.backendUtilityService.addRxJsResource(this.rxjs);
1871
+ this.filterFactory.addRxJsResource(this.rxjs);
1872
+ this.filterService.addRxJsResource(this.rxjs);
1873
+ this.sortService.addRxJsResource(this.rxjs);
1874
+ this.paginationService.addRxJsResource(this.rxjs);
1875
+ this.containerService.registerInstance('RxJsResource', this.rxjs);
1876
+ }
1877
+ /**
1878
+ * Render (or dispose) the Pagination Component, user can optionally provide False (to not show it) which will in term dispose of the Pagination,
1879
+ * also while disposing we can choose to omit the disposable of the Pagination Service (if we are simply toggling the Pagination, we want to keep the Service alive)
1880
+ * @param {Boolean} showPagination - show (new render) or not (dispose) the Pagination
1881
+ * @param {Boolean} shouldDisposePaginationService - when disposing the Pagination, do we also want to dispose of the Pagination Service? (defaults to True)
1882
+ */
1883
+ renderPagination(showPagination = true) {
1884
+ if (this.gridOptions?.enablePagination && !this._isPaginationInitialized && showPagination) {
1885
+ this.slickPagination = new SlickPaginationComponent(this.paginationService, this._eventPubSubService, this.sharedService, this.translaterService);
1886
+ this.slickPagination.renderPagination(this.gridContainerElement);
1887
+ this._isPaginationInitialized = true;
1888
+ }
1889
+ else if (!showPagination) {
1890
+ if (this.slickPagination) {
1891
+ this.slickPagination.dispose();
1892
+ }
1893
+ this._isPaginationInitialized = false;
1894
+ }
1895
+ }
1896
+ /**
1897
+ * Takes a flat dataset with parent/child relationship, sort it (via its tree structure) and return the sorted flat array
1898
+ * @param {Array<Object>} flatDatasetInput - flat dataset input
1899
+ * @param {Boolean} forceGridRefresh - optionally force a full grid refresh
1900
+ * @returns {Array<Object>} sort flat parent/child dataset
1901
+ */
1902
+ sortTreeDataset(flatDatasetInput, forceGridRefresh = false) {
1903
+ const prevDatasetLn = this._currentDatasetLength;
1904
+ let sortedDatasetResult;
1905
+ let flatDatasetOutput = [];
1906
+ // if the hierarchical dataset was already initialized then no need to re-convert it, we can use it directly from the shared service ref
1907
+ if (this._isDatasetHierarchicalInitialized && this.datasetHierarchical) {
1908
+ sortedDatasetResult = this.treeDataService.sortHierarchicalDataset(this.datasetHierarchical);
1909
+ flatDatasetOutput = sortedDatasetResult.flat;
1910
+ }
1911
+ else if (Array.isArray(flatDatasetInput) && flatDatasetInput.length > 0) {
1912
+ if (this.gridOptions?.treeDataOptions?.initialSort) {
1913
+ // else we need to first convert the flat dataset to a hierarchical dataset and then sort
1914
+ sortedDatasetResult = this.treeDataService.convertFlatParentChildToTreeDatasetAndSort(flatDatasetInput, this._columnDefinitions, this.gridOptions);
1915
+ this.sharedService.hierarchicalDataset = sortedDatasetResult.hierarchical;
1916
+ flatDatasetOutput = sortedDatasetResult.flat;
1917
+ }
1918
+ else {
1919
+ // else we assume that the user provided an array that is already sorted (user's responsability)
1920
+ // and so we can simply convert the array to a tree structure and we're done, no need to sort
1921
+ this.sharedService.hierarchicalDataset = this.treeDataService.convertFlatParentChildToTreeDataset(flatDatasetInput, this.gridOptions);
1922
+ flatDatasetOutput = flatDatasetInput || [];
1923
+ }
1924
+ }
1925
+ // if we add/remove item(s) from the dataset, we need to also refresh our tree data filters
1926
+ if (flatDatasetInput.length > 0 && (forceGridRefresh || flatDatasetInput.length !== prevDatasetLn)) {
1927
+ this.filterService.refreshTreeDataFilters(flatDatasetOutput);
1928
+ }
1929
+ return flatDatasetOutput;
1930
+ }
1931
+ /**
1932
+ * For convenience to the user, we provide the property "editor" as an Angular-Slickgrid editor complex object
1933
+ * however "editor" is used internally by SlickGrid for it's own Editor Factory
1934
+ * so in our lib we will swap "editor" and copy it into a new property called "internalColumnEditor"
1935
+ * then take back "editor.model" and make it the new "editor" so that SlickGrid Editor Factory still works
1936
+ */
1937
+ swapInternalEditorToSlickGridFactoryEditor(columnDefinitions) {
1938
+ if (columnDefinitions.some(col => `${col.id}`.includes('.'))) {
1939
+ console.error('[Angular-Slickgrid] Make sure that none of your Column Definition "id" property includes a dot in its name because that will cause some problems with the Editors. For example if your column definition "field" property is "user.firstName" then use "firstName" as the column "id".');
1940
+ }
1941
+ return columnDefinitions.map((column) => {
1942
+ // on every Editor that have a "collectionAsync", resolve the data and assign it to the "collection" property
1943
+ if (column && column.editor && column.editor.collectionAsync) {
1944
+ this.loadEditorCollectionAsync(column);
1945
+ }
1946
+ return { ...column, editor: column.editor && column.editor.model, internalColumnEditor: { ...column.editor } };
1947
+ });
1948
+ }
1949
+ translateColumnHeaderTitleKeys() {
1950
+ // translate all columns (including hidden columns)
1951
+ this.extensionUtility.translateItems(this.sharedService.allColumns, 'nameKey', 'name');
1952
+ }
1953
+ translateColumnGroupKeys() {
1954
+ // translate all column groups (including hidden columns)
1955
+ this.extensionUtility.translateItems(this.sharedService.allColumns, 'columnGroupKey', 'columnGroup');
1956
+ }
1957
+ /**
1958
+ * Update the "internalColumnEditor.collection" property.
1959
+ * Since this is called after the async call resolves, the pointer will not be the same as the "column" argument passed.
1960
+ * Once we found the new pointer, we will reassign the "editor" and "collection" to the "internalColumnEditor" so it has newest collection
1961
+ */
1962
+ updateEditorCollection(column, newCollection) {
1963
+ column.editor.collection = newCollection;
1964
+ column.editor.disabled = false;
1965
+ // find the new column reference pointer & re-assign the new editor to the internalColumnEditor
1966
+ const columns = this.slickGrid.getColumns();
1967
+ if (Array.isArray(columns)) {
1968
+ const columnRef = columns.find((col) => col.id === column.id);
1969
+ if (columnRef) {
1970
+ columnRef.internalColumnEditor = column.editor;
1971
+ }
1972
+ }
1973
+ // get current Editor, remove it from the DOM then re-enable it and re-render it with the new collection.
1974
+ const currentEditor = this.slickGrid.getCellEditor();
1975
+ if (currentEditor?.disable && currentEditor?.renderDomElement) {
1976
+ currentEditor.destroy();
1977
+ currentEditor.disable(false);
1978
+ currentEditor.renderDomElement(newCollection);
1979
+ }
1980
+ }
1981
+ }
1982
+ AngularSlickgridComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: AngularSlickgridComponent, deps: [{ token: AngularUtilService }, { token: i0.ApplicationRef }, { token: i0.ChangeDetectorRef }, { token: ContainerService }, { token: i0.ElementRef }, { token: i1.TranslateService, optional: true }, { token: TranslaterService, optional: true }, { token: 'config' }, { token: 'externalService' }], target: i0.ɵɵFactoryTarget.Component });
1983
+ AngularSlickgridComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "12.0.0", version: "13.1.3", type: AngularSlickgridComponent, selector: "angular-slickgrid", inputs: { customDataView: "customDataView", gridId: "gridId", gridOptions: "gridOptions", paginationOptions: "paginationOptions", columnDefinitions: "columnDefinitions", dataset: "dataset", datasetHierarchical: "datasetHierarchical" }, providers: [
1984
+ // make everything transient (non-singleton)
1985
+ AngularUtilService,
1986
+ ApplicationRef,
1987
+ TranslaterService,
1988
+ ], ngImport: i0, template: "<div id=\"slickGridContainer-{{gridId}}\" class=\"gridPane\">\r\n <div attr.id='{{gridId}}' class=\"slickgrid-container\" style=\"width: 100%\">\r\n </div>\r\n</div>" });
1989
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: AngularSlickgridComponent, decorators: [{
1990
+ type: Component,
1991
+ args: [{ selector: 'angular-slickgrid', providers: [
1992
+ // make everything transient (non-singleton)
1993
+ AngularUtilService,
1994
+ ApplicationRef,
1995
+ TranslaterService,
1996
+ ], template: "<div id=\"slickGridContainer-{{gridId}}\" class=\"gridPane\">\r\n <div attr.id='{{gridId}}' class=\"slickgrid-container\" style=\"width: 100%\">\r\n </div>\r\n</div>" }]
1997
+ }], ctorParameters: function () { return [{ type: AngularUtilService }, { type: i0.ApplicationRef }, { type: i0.ChangeDetectorRef }, { type: ContainerService }, { type: i0.ElementRef }, { type: i1.TranslateService, decorators: [{
1998
+ type: Optional
1999
+ }] }, { type: TranslaterService, decorators: [{
2000
+ type: Optional
2001
+ }] }, { type: undefined, decorators: [{
2002
+ type: Inject,
2003
+ args: ['config']
2004
+ }] }, { type: undefined, decorators: [{
2005
+ type: Inject,
2006
+ args: ['externalService']
2007
+ }] }]; }, propDecorators: { customDataView: [{
2008
+ type: Input
2009
+ }], gridId: [{
2010
+ type: Input
2011
+ }], gridOptions: [{
2012
+ type: Input
2013
+ }], paginationOptions: [{
2014
+ type: Input
2015
+ }], columnDefinitions: [{
2016
+ type: Input
2017
+ }], dataset: [{
2018
+ type: Input
2019
+ }], datasetHierarchical: [{
2020
+ type: Input
2021
+ }] } });
2022
+
2023
+ class AngularSlickgridModule {
2024
+ static forRoot(config = {}) {
2025
+ return {
2026
+ ngModule: AngularSlickgridModule,
2027
+ providers: [
2028
+ { provide: 'config', useValue: config },
2029
+ { provide: 'externalService', useValue: null },
2030
+ AngularUtilService,
2031
+ BsDropDownService,
2032
+ ContainerService,
2033
+ ]
2034
+ };
2035
+ }
2036
+ }
2037
+ AngularSlickgridModule.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: AngularSlickgridModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule });
2038
+ AngularSlickgridModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: AngularSlickgridModule, declarations: [AngularSlickgridComponent], imports: [CommonModule,
2039
+ TranslateModule], exports: [AngularSlickgridComponent] });
2040
+ AngularSlickgridModule.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: AngularSlickgridModule, imports: [[
2041
+ CommonModule,
2042
+ TranslateModule
2043
+ ]] });
2044
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "13.1.3", ngImport: i0, type: AngularSlickgridModule, decorators: [{
2045
+ type: NgModule,
2046
+ args: [{
2047
+ imports: [
2048
+ CommonModule,
2049
+ TranslateModule
2050
+ ],
2051
+ declarations: [
2052
+ AngularSlickgridComponent,
2053
+ ],
2054
+ exports: [
2055
+ AngularSlickgridComponent,
2056
+ ],
2057
+ entryComponents: [AngularSlickgridComponent]
2058
+ }]
2059
+ }] });
2060
+
2061
+ /**
2062
+ * Generated bundle index. Do not edit.
2063
+ */
2064
+
2065
+ export { AngularSlickgridComponent, AngularSlickgridModule, AngularUtilService, BsDropDownService, SlickRowDetailView, SlickgridConfig, unsubscribeAllObservables };
2066
+ //# sourceMappingURL=angular-slickgrid.mjs.map