From ffe7dc4c2a7ae778c8e731fd7637b154c10035f0 Mon Sep 17 00:00:00 2001 From: ghiscoding Date: Wed, 12 May 2021 12:50:17 -0400 Subject: [PATCH] feat(resizer): add `resizeByContentOnlyOnFirstLoad` grid option - in many cases doing a resize by content only the first time we get data is enough (default is true) and so this flag will handle that scenario or else if the user always want to resize anytime the data changes then the user could disable this new flag --- .../src/examples/example14.html | 3 ++- .../src/examples/example14.ts | 11 +++++++++++ packages/common/src/global-grid-options.ts | 1 + .../src/interfaces/gridOption.interface.ts | 15 ++++++++++++--- .../__tests__/slick-vanilla-grid.spec.ts | 16 +++++++++++++++- .../src/components/slick-vanilla-grid-bundle.ts | 2 +- .../src/services/resizer.service.ts | 5 ++++- 7 files changed, 46 insertions(+), 7 deletions(-) diff --git a/examples/webpack-demo-vanilla-bundle/src/examples/example14.html b/examples/webpack-demo-vanilla-bundle/src/examples/example14.html index 7cce24bb7..e3ad6d9e0 100644 --- a/examples/webpack-demo-vanilla-bundle/src/examples/example14.html +++ b/examples/webpack-demo-vanilla-bundle/src/examples/example14.html @@ -64,10 +64,11 @@

Container Width (1000px)

Save All

+
-
\ No newline at end of file + diff --git a/examples/webpack-demo-vanilla-bundle/src/examples/example14.ts b/examples/webpack-demo-vanilla-bundle/src/examples/example14.ts index b5ca8cfda..d71b749d9 100644 --- a/examples/webpack-demo-vanilla-bundle/src/examples/example14.ts +++ b/examples/webpack-demo-vanilla-bundle/src/examples/example14.ts @@ -89,6 +89,7 @@ export class Example14 { editedItems = {}; sgb1: SlickVanillaGridBundle; gridContainerElm: HTMLDivElement; + loadingClass = ''; complexityLevelList = [ { value: 0, label: 'Very Simple' }, { value: 1, label: 'Simple' }, @@ -117,6 +118,8 @@ export class Example14 { this._bindingEventService.bind(this.gridContainerElm, 'onbeforeeditcell', this.handleOnBeforeEditCell.bind(this)); this._bindingEventService.bind(this.gridContainerElm, 'oncellchange', this.handleOnCellChange.bind(this)); this._bindingEventService.bind(this.gridContainerElm, 'onpaginationchanged', this.handlePaginationChanged.bind(this)); + this._bindingEventService.bind(this.gridContainerElm, 'onbeforeresizebycontent', this.showSpinner.bind(this)); + this._bindingEventService.bind(this.gridContainerElm, 'onafterresizebycontent', this.hideSpinner.bind(this)); } dispose() { @@ -415,6 +418,14 @@ export class Example14 { }; } + hideSpinner() { + setTimeout(() => this.loadingClass = '', 200); // delay the hide spinner a bit to avoid show/hide too quickly + } + + showSpinner() { + this.loadingClass = 'mdi mdi-load mdi-spin-1s mdi-24px color-alt-success'; + } + loadData(count: number) { // mock data const tmpArray = []; diff --git a/packages/common/src/global-grid-options.ts b/packages/common/src/global-grid-options.ts index 3c2971fe7..02f705b90 100644 --- a/packages/common/src/global-grid-options.ts +++ b/packages/common/src/global-grid-options.ts @@ -234,6 +234,7 @@ export const GlobalGridOptions: GridOption = { topPanelHeight: 30, translationNamespaceSeparator: ':', resizeAlwaysRecalculateColumnWidth: false, + resizeByContentOnlyOnFirstLoad: true, resizeCellCharWidthInPx: 7.8, resizeCellPaddingWidthInPx: 14, resizeFormatterPaddingWidthInPx: 0, diff --git a/packages/common/src/interfaces/gridOption.interface.ts b/packages/common/src/interfaces/gridOption.interface.ts index 2cc1c75e5..705f60036 100644 --- a/packages/common/src/interfaces/gridOption.interface.ts +++ b/packages/common/src/interfaces/gridOption.interface.ts @@ -479,24 +479,33 @@ export interface GridOption { /** defaults to false, if a column `width` is provided (or was previously calculated) should we recalculate it or not when resizing by cell content? */ resizeAlwaysRecalculateColumnWidth?: boolean; + /** + * defaults to true, do we want to resize the grid by content only on the first page or anytime the data changes? + * Requires `enableAutoResizeColumnsByCellContent` to be set. + * Also don't get confused with `autosizeColumnsByCellContentOnFirstLoad` that flag won't block resize by content after the first load while `resizeByContentOnlyOnFirstLoad` + */ + resizeByContentOnlyOnFirstLoad?: boolean; + /** * Defaults to 7, width in pixels of a string character which is used by the resize columns by its content, this can vary depending on which font family/size is used & cell padding. * This is only used when resizing the columns width by their content, we need to know the width of a character in pixel to do all calculations. + * Requires `enableAutoResizeColumnsByCellContent` to be set. */ resizeCellCharWidthInPx?: number; - /** Defaults to 6, cell padding width to add to the calculation when resizing columns by their cell text content. */ + /** Defaults to 6, cell padding width to add to the calculation when resizing columns by their cell text content (requires `enableAutoResizeColumnsByCellContent` to be set) */ resizeCellPaddingWidthInPx?: number; - /** Defaults to around ~0.9, what is the ratio to use (on field `type` "string" only) in the calculation when resizing columns by their cell text content. */ + /** Defaults to around ~0.9, what is the ratio to use (on field `type` "string" only) in the calculation when resizing columns by their cell text content (requires `enableAutoResizeColumnsByCellContent` to be set). */ resizeDefaultRatioForStringType?: number; - /** Defaults to 6, padding width to add to the calculation when using a Formatter and resizing columns by their cell text content. */ + /** Defaults to 6, padding width to add to the calculation when using a Formatter and resizing columns by their cell text content (requires `enableAutoResizeColumnsByCellContent` to be set). */ resizeFormatterPaddingWidthInPx?: number; /** * Defaults to 1000, width in pixels of a string character which is used by the resize columns by its content, this can vary depending on which font family/size is used & cell padding. * This is only used when resizing the columns width by their content, we need to know the width of a character in pixel to do all calculations. + * Requires `enableAutoResizeColumnsByCellContent` to be set. */ resizeMaxItemToInspectCellContentWidth?: number; diff --git a/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts b/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts index 73e0fc66a..5c7e194cf 100644 --- a/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts +++ b/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts @@ -1766,7 +1766,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () const resizeContentSpy = jest.spyOn(resizerServiceStub, 'resizeColumnsByCellContent'); jest.spyOn(mockDataView, 'getLength').mockReturnValue(1); - component.gridOptions = { enablePagination: false, showCustomFooter: true, autoFitColumnsOnFirstLoad: false, enableAutoSizeColumns: false, enableAutoResizeColumnsByCellContent: true }; + component.gridOptions = { enablePagination: false, resizeByContentOnlyOnFirstLoad: false, showCustomFooter: true, autoFitColumnsOnFirstLoad: false, enableAutoSizeColumns: false, enableAutoResizeColumnsByCellContent: true }; component.initialization(divContainer, slickEventHandler); mockDataView.onSetItemsCalled.notify({ idProperty: 'id', itemCount: 1 }); @@ -1775,6 +1775,20 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () done(); }, 10); }); + + it('should call "resizeColumnsByCellContent" when the DataView "onSetItemsCalled" event is triggered and "enableAutoResizeColumnsByCellContent" and "resizeColumnsByCellContent" are both set', (done) => { + const resizeContentSpy = jest.spyOn(resizerServiceStub, 'resizeColumnsByCellContent'); + jest.spyOn(mockDataView, 'getLength').mockReturnValue(1); + + component.gridOptions = { enablePagination: false, resizeByContentOnlyOnFirstLoad: true, showCustomFooter: true, autoFitColumnsOnFirstLoad: false, enableAutoSizeColumns: false, enableAutoResizeColumnsByCellContent: true }; + component.initialization(divContainer, slickEventHandler); + mockDataView.onSetItemsCalled.notify({ idProperty: 'id', itemCount: 1 }); + + setTimeout(() => { + expect(resizeContentSpy).toHaveBeenCalledWith(false); + done(); + }, 10); + }); }); describe('Custom Footer', () => { diff --git a/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts b/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts index 09517e0f0..0b3391fbb 100644 --- a/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts +++ b/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts @@ -846,7 +846,7 @@ export class SlickVanillaGridBundle { if (args.itemCount > 0 && (this.gridOptions.autosizeColumnsByCellContentOnFirstLoad || this.gridOptions.enableAutoResizeColumnsByCellContent)) { // add a delay so that if column positions changes by changeColumnsArrangement() when using custom Grid Views // or presets.columns won't have any impact on the list of visible columns and their positions - setTimeout(() => this.resizerService.resizeColumnsByCellContent(true), 10); + setTimeout(() => this.resizerService.resizeColumnsByCellContent(!this.gridOptions?.resizeByContentOnlyOnFirstLoad), 10); } }); diff --git a/packages/vanilla-bundle/src/services/resizer.service.ts b/packages/vanilla-bundle/src/services/resizer.service.ts index 94276f9ca..b1a8812a0 100644 --- a/packages/vanilla-bundle/src/services/resizer.service.ts +++ b/packages/vanilla-bundle/src/services/resizer.service.ts @@ -31,6 +31,7 @@ export class ResizerService { private _intervalExecutionCounter = 0; private _intervalRetryDelay = DEFAULT_INTERVAL_RETRY_DELAY; private _isStopResizeIntervalRequested = false; + private _hasResizedByContentAtLeastOnce = false; private _lastDimensions?: GridSize; private _totalColumnsWidthByContent = 0; @@ -157,9 +158,10 @@ export class ResizerService { const columnWidths: { [columnId in string | number]: number; } = {}; let reRender = false; - if (!Array.isArray(dataset) || dataset.length === 0) { + if ((!Array.isArray(dataset) || dataset.length === 0) || (this._hasResizedByContentAtLeastOnce && this.gridOptions?.resizeByContentOnlyOnFirstLoad && !recalculateColumnsTotalWidth)) { return; } + this.eventPubSubService.publish('onBeforeResizeByContent'); let readItemCount = 0; @@ -255,6 +257,7 @@ export class ResizerService { // send updated column definitions widths to SlickGrid this._grid.setColumns(columnDefinitions); + this._hasResizedByContentAtLeastOnce = true; const calculateColumnWidths: { [columnId in string | number]: number | undefined; } = {}; for (const columnDef of columnDefinitions) {