angular-slickgrid 8.12.1 → 8.13.1

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.
@@ -1,7 +1,7 @@
1
- import { unsubscribeAll, SlickRowSelectionModel, castObservableToPromise, addToArrayWhenNotExists, Filters, OperatorType, EventNamingStyle, FileType, DelimiterType, SlickEventHandler, SlickgridConfig as SlickgridConfig$1, BackendUtilityService, GridEventService, SharedService, CollectionService, ExtensionUtility, FilterFactory, FilterService, ResizerService, SortService, TreeDataService, PaginationService, ExtensionService, GridStateService, GridService, HeaderGroupingService, emptyElement, SlickGroupItemMetadataProvider, SlickDataView, autoAddEditorFormatterToColumnsWithEditor, SlickGrid, GridStateType, ExtensionName, isColumnDateType } from '@slickgrid-universal/common';
1
+ import { unsubscribeAll, SlickRowSelectionModel, SlickEventData, castObservableToPromise, addToArrayWhenNotExists, FileType, DelimiterType, EventNamingStyle, OperatorType, Filters, SlickEventHandler, SlickgridConfig as SlickgridConfig$1, BackendUtilityService, GridEventService, SharedService, CollectionService, ExtensionUtility, FilterFactory, FilterService, ResizerService, SortService, TreeDataService, PaginationService, ExtensionService, GridStateService, GridService, HeaderGroupingService, emptyElement, SlickGroupItemMetadataProvider, SlickDataView, autoAddEditorFormatterToColumnsWithEditor, SlickGrid, GridStateType, ExtensionName, isColumnDateType } from '@slickgrid-universal/common';
2
2
  export * from '@slickgrid-universal/common';
3
3
  import * as i0 from '@angular/core';
4
- import { Injectable, Optional, EventEmitter, Component, Inject, Input, Output, ContentChild, NgModule } from '@angular/core';
4
+ import { Injectable, Optional, EventEmitter, ContentChild, Input, Output, Inject, Component, NgModule } from '@angular/core';
5
5
  import * as i1 from '@ngx-translate/core';
6
6
  import { TranslateModule } from '@ngx-translate/core';
7
7
  import { SlickRowDetailView as SlickRowDetailView$1 } from '@slickgrid-universal/row-detail-view-plugin';
@@ -67,7 +67,10 @@ class AngularUtilService {
67
67
  domElem = viewRef.rootNodes[0];
68
68
  // when user provides the DOM element target, we will read the new Component html and use it to replace the target html
69
69
  if (targetElement && domElem) {
70
- targetElement.innerHTML = domElem.innerHTML;
70
+ targetElement.innerHTML =
71
+ typeof createCompOptions?.sanitizer === 'function'
72
+ ? createCompOptions.sanitizer(domElem.innerHTML || '')
73
+ : domElem.innerHTML;
71
74
  }
72
75
  }
73
76
  return { componentRef, domElement: domElem };
@@ -194,6 +197,7 @@ class SlickRowDetailView extends SlickRowDetailView$1 {
194
197
  rxjs;
195
198
  rowDetailContainer;
196
199
  _preloadComponent;
200
+ _preloadCompRef;
197
201
  _views = [];
198
202
  _viewComponent;
199
203
  _subscriptions = [];
@@ -236,8 +240,12 @@ class SlickRowDetailView extends SlickRowDetailView$1 {
236
240
  }
237
241
  /** Dispose of all the opened Row Detail Panels Angular View Components */
238
242
  disposeAllViewComponents() {
239
- this._views.forEach((compRef) => this.disposeViewComponent(compRef));
240
- this._views = [];
243
+ do {
244
+ const view = this._views.pop();
245
+ if (view) {
246
+ this.disposeView(view);
247
+ }
248
+ } while (this._views.length > 0);
241
249
  }
242
250
  /** Get the instance of the SlickGrid addon (control or plugin). */
243
251
  getAddonInstance() {
@@ -292,6 +300,8 @@ class SlickRowDetailView extends SlickRowDetailView$1 {
292
300
  }
293
301
  if (this.onAsyncEndUpdate) {
294
302
  this.eventHandler.subscribe(this.onAsyncEndUpdate, (e, args) => {
303
+ // destroy preload if exists
304
+ this._preloadCompRef?.destroy();
295
305
  // triggers after backend called "onAsyncResponse.notify()"
296
306
  this.renderViewModel(args?.item);
297
307
  if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAsyncEndUpdate === 'function') {
@@ -304,7 +314,6 @@ class SlickRowDetailView extends SlickRowDetailView$1 {
304
314
  // display preload template & re-render all the other Detail Views after toggling
305
315
  // the preload View will eventually go away once the data gets loaded after the "onAsyncEndUpdate" event
306
316
  this.renderPreloadView();
307
- this.renderAllViewComponents();
308
317
  if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onAfterRowDetailToggle === 'function') {
309
318
  this.rowDetailViewOptions.onAfterRowDetailToggle(e, args);
310
319
  }
@@ -329,6 +338,14 @@ class SlickRowDetailView extends SlickRowDetailView$1 {
329
338
  }
330
339
  });
331
340
  }
341
+ if (this.onBeforeRowOutOfViewportRange) {
342
+ this._eventHandler.subscribe(this.onBeforeRowOutOfViewportRange, (event, args) => {
343
+ if (typeof this.rowDetailViewOptions?.onBeforeRowOutOfViewportRange === 'function') {
344
+ this.rowDetailViewOptions.onBeforeRowOutOfViewportRange(event, args);
345
+ }
346
+ this.disposeViewByItem(args.item);
347
+ });
348
+ }
332
349
  if (this.onRowOutOfViewportRange) {
333
350
  this.eventHandler.subscribe(this.onRowOutOfViewportRange, (e, args) => {
334
351
  if (this.rowDetailViewOptions && typeof this.rowDetailViewOptions.onRowOutOfViewportRange === 'function') {
@@ -354,15 +371,10 @@ class SlickRowDetailView extends SlickRowDetailView$1 {
354
371
  }
355
372
  /** Redraw (re-render) all the expanded row detail View Components */
356
373
  redrawAllViewComponents() {
357
- this._views.forEach((compRef) => {
358
- this.redrawViewComponent(compRef);
359
- });
360
- }
361
- /** Render all the expanded row detail View Components */
362
- renderAllViewComponents() {
374
+ this.resetRenderedRows();
363
375
  this._views.forEach((view) => {
364
- if (view?.dataContext) {
365
- this.renderViewModel(view.dataContext);
376
+ if (!view.rendered) {
377
+ this.redrawViewComponent(view);
366
378
  }
367
379
  });
368
380
  }
@@ -377,24 +389,29 @@ class SlickRowDetailView extends SlickRowDetailView$1 {
377
389
  renderPreloadView() {
378
390
  const containerElements = this.gridContainerElement.getElementsByClassName(`${PRELOAD_CONTAINER_PREFIX}`);
379
391
  if (this._preloadComponent && containerElements?.length >= 0) {
380
- this.angularUtilService.createAngularComponentAppendToDom(this._preloadComponent, containerElements[containerElements.length - 1]);
392
+ const preloadComp = this.angularUtilService.createAngularComponentAppendToDom(this._preloadComponent, containerElements[containerElements.length - 1], {}, { sanitizer: this._grid.sanitizeHtmlString });
393
+ this._preloadCompRef = preloadComp.componentRef;
381
394
  }
382
395
  }
383
396
  /** Render (or re-render) the View Component (Row Detail) */
384
397
  renderViewModel(item) {
385
398
  const containerElements = this.gridContainerElement.getElementsByClassName(`${ROW_DETAIL_CONTAINER_PREFIX}${item[this.datasetIdPropName]}`);
386
399
  if (this._viewComponent && containerElements?.length > 0) {
400
+ // render row detail
387
401
  const componentOutput = this.angularUtilService.createAngularComponentAppendToDom(this._viewComponent, containerElements[containerElements.length - 1], {
388
402
  model: item,
389
403
  addon: this,
390
404
  grid: this._grid,
391
405
  dataView: this.dataView,
392
406
  parent: this.rowDetailViewOptions?.parent,
407
+ }, {
408
+ sanitizer: this._grid.sanitizeHtmlString,
393
409
  });
394
410
  if (componentOutput?.componentRef) {
395
411
  const viewObj = this._views.find((obj) => obj.id === item[this.datasetIdPropName]);
396
412
  if (viewObj) {
397
413
  viewObj.componentRef = componentOutput.componentRef;
414
+ viewObj.rendered = true;
398
415
  }
399
416
  return viewObj;
400
417
  }
@@ -404,12 +421,23 @@ class SlickRowDetailView extends SlickRowDetailView$1 {
404
421
  // --
405
422
  // protected functions
406
423
  // ------------------
407
- disposeViewComponent(expandedView) {
424
+ disposeViewByItem(item, removeFromArray = false) {
425
+ const foundViewIndex = this._views.findIndex((view) => view.id === item[this.datasetIdPropName]);
426
+ if (foundViewIndex >= 0 && foundViewIndex in this._views) {
427
+ const expandedView = this._views[foundViewIndex];
428
+ this.disposeView(expandedView);
429
+ if (removeFromArray) {
430
+ this._views.splice(foundViewIndex, 1);
431
+ }
432
+ }
433
+ }
434
+ disposeView(expandedView) {
408
435
  const compRef = expandedView?.componentRef;
409
436
  if (compRef) {
410
437
  this.appRef.detachView(compRef.hostView);
411
438
  if (compRef?.destroy) {
412
439
  compRef.destroy();
440
+ expandedView.rendered = false;
413
441
  }
414
442
  return expandedView;
415
443
  }
@@ -421,7 +449,7 @@ class SlickRowDetailView extends SlickRowDetailView$1 {
421
449
  */
422
450
  notifyTemplate(item) {
423
451
  if (this.onAsyncResponse) {
424
- this.onAsyncResponse.notify({ item, itemDetail: item }, undefined, this);
452
+ this.onAsyncResponse.notify({ item, itemDetail: item }, new SlickEventData(), this);
425
453
  }
426
454
  }
427
455
  /**
@@ -461,27 +489,21 @@ class SlickRowDetailView extends SlickRowDetailView$1 {
461
489
  const viewInfo = {
462
490
  id: args.item[this.datasetIdPropName],
463
491
  dataContext: args.item,
492
+ rendered: false,
464
493
  };
465
494
  const idPropName = this.gridOptions.datasetIdPropertyName || 'id';
466
495
  addToArrayWhenNotExists(this._views, viewInfo, idPropName);
467
496
  }
468
497
  else {
469
498
  // collapsing, so dispose of the View/Component
470
- const foundViewIndex = this._views.findIndex((view) => view.id === args.item[this.datasetIdPropName]);
471
- if (foundViewIndex >= 0 && foundViewIndex in this._views) {
472
- const compRef = this._views[foundViewIndex].componentRef;
473
- if (compRef) {
474
- this.appRef.detachView(compRef.hostView);
475
- compRef.destroy();
476
- }
477
- this._views.splice(foundViewIndex, 1);
478
- }
499
+ this.disposeViewByItem(args.item, true);
479
500
  }
480
501
  }
481
502
  /** When Row comes back to Viewport Range, we need to redraw the View */
482
503
  handleOnRowBackToViewportRange(_e, args) {
483
- if (args?.item) {
484
- this.redrawAllViewComponents();
504
+ const viewModel = Array.from(this._views).find((x) => x.id === args.rowId);
505
+ if (viewModel && !viewModel.rendered) {
506
+ this.redrawViewComponent(viewModel);
485
507
  }
486
508
  }
487
509
  }
@@ -707,7 +729,6 @@ const GlobalGridOptions = {
707
729
  panelRows: 1,
708
730
  keyPrefix: '__',
709
731
  useRowClick: false,
710
- useSimpleViewportCalc: true,
711
732
  saveDetailViewOnScroll: false,
712
733
  },
713
734
  rowHeight: 35,
@@ -1531,6 +1552,13 @@ class AngularSlickgridComponent {
1531
1552
  }
1532
1553
  return showing;
1533
1554
  }
1555
+ /**
1556
+ * Toggle the empty data warning message visibility.
1557
+ * @param showWarning
1558
+ */
1559
+ displayEmptyDataWarning(showWarning = true) {
1560
+ this.slickEmptyWarning?.showEmptyDataMessage(showWarning);
1561
+ }
1534
1562
  //
1535
1563
  // protected functions
1536
1564
  // ------------------
@@ -1541,9 +1569,6 @@ class AngularSlickgridComponent {
1541
1569
  copyColumnWidthsReference(columnDefinitions) {
1542
1570
  columnDefinitions.forEach((col) => (col.originalWidth = col.width));
1543
1571
  }
1544
- displayEmptyDataWarning(showWarning = true) {
1545
- this.slickEmptyWarning?.showEmptyDataMessage(showWarning);
1546
- }
1547
1572
  bindDifferentHooks(grid, gridOptions, dataView) {
1548
1573
  // on locale change, we have to manually translate the Headers, GridMenu
1549
1574
  if (this.translate?.onLangChange) {
@@ -1610,8 +1635,14 @@ class AngularSlickgridComponent {
1610
1635
  this.loadColumnPresetsWhenDatasetInitialized();
1611
1636
  this.loadFilterPresetsWhenDatasetInitialized();
1612
1637
  // When data changes in the DataView, we need to refresh the metrics and/or display a warning if the dataset is empty
1613
- this._eventHandler.subscribe(dataView.onRowCountChanged, () => {
1614
- grid.invalidate();
1638
+ this._eventHandler.subscribe(dataView.onRowCountChanged, (_e, args) => {
1639
+ if (!gridOptions.enableRowDetailView || !Array.isArray(args.changedRows) || args.changedRows.length === args.itemCount) {
1640
+ grid.invalidate();
1641
+ }
1642
+ else {
1643
+ grid.invalidateRows(args.changedRows);
1644
+ grid.render();
1645
+ }
1615
1646
  this.handleOnItemCountChanged(dataView.getFilteredItemCount() || 0, dataView.getItemCount() || 0);
1616
1647
  });
1617
1648
  this._eventHandler.subscribe(dataView.onSetItemsCalled, (_e, args) => {