Skip to content

Commit

Permalink
feat(resizer): add resizeByContentOnlyOnFirstLoad grid option
Browse files Browse the repository at this point in the history
- 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
  • Loading branch information
ghiscoding committed May 12, 2021
1 parent f214b2e commit 135771e
Show file tree
Hide file tree
Showing 8 changed files with 197 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -686,6 +686,17 @@ describe('Angular-Slickgrid Custom Component instantiated via Constructor', () =
expect(syncSpy).toHaveBeenCalledWith(component.grid, false);
});

it('should destroy customElement and its DOM element when requested', () => {
const spy = jest.spyOn(component, 'emptyGridContainerElm');

component.gridOptions = { enableFiltering: true } as GridOption;
component.ngAfterViewInit();
component.destroy(true);

expect(spy).toHaveBeenCalledWith();
});


it('should bind local filter when "enableFiltering" is set', () => {
const bindLocalSpy = jest.spyOn(filterServiceStub, 'bindLocalOnFilter');

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,7 @@ describe('App Component', () => {
const mockDataset = [{ id: 1, firstName: 'John' }, { id: 2, firstName: 'Jane' }];

component.gridId = 'grid1';
component.gridOptions = { enablePagination: false, showCustomFooter: true, autoFitColumnsOnFirstLoad: false, enableAutoSizeColumns: false, enableAutoResizeColumnsByCellContent: true } as GridOption;
component.gridOptions = { enablePagination: false, resizeByContentOnlyOnFirstLoad: false, showCustomFooter: true, autoFitColumnsOnFirstLoad: false, enableAutoSizeColumns: false, enableAutoResizeColumnsByCellContent: true } as GridOption;
component.dataset = mockDataset;
fixture.detectChanges();
component.dataView.onSetItemsCalled.notify({ idProperty: 'id', itemCount: 1 });
Expand All @@ -323,111 +323,127 @@ describe('App Component', () => {
done();
}, 10);
});
});

describe('Custom Footer', () => {
it('should display 1 items selected on the left side footer section after triggering "onSelectedRowsChanged" event', () => {
const mockColDefs = [{ id: 'name', field: 'name', editor: undefined, internalColumnEditor: {} }];
it('should call "resizeColumnsByCellContent" when the DataView "onSetItemsCalled" event is triggered and "enableAutoResizeColumnsByCellContent" is set', (done) => {
const resizeContentSpy = jest.spyOn(resizerServiceStub, 'resizeColumnsByCellContent');
const mockDataset = [{ id: 1, firstName: 'John' }, { id: 2, firstName: 'Jane' }];

component.gridId = 'grid1';
component.gridOptions = {
enablePagination: false,
showCustomFooter: true,
enableCheckboxSelector: true,
customFooterOptions: {
hideRowSelectionCount: false
}
} as GridOption;
fixture.detectChanges();
component.columnDefinitions = mockColDefs;
component.grid.setSelectionModel(new Slick.CellSelectionModel());
component.grid.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [] });
fixture.detectChanges();

const gridContainerElm = document.querySelector('.slickgrid-container') as HTMLDivElement;
const gridPaneElm = document.querySelector('.gridPane') as HTMLDivElement;
const footerContainerElm = document.querySelector('div.slick-custom-footer') as HTMLDivElement;
const leftFooterElm = document.querySelector('div.slick-custom-footer > div.left-footer') as HTMLSpanElement;
const rightFooterElm = document.querySelector('div.slick-custom-footer > div.metrics') as HTMLSpanElement;

expect(gridPaneElm.id).toBe('slickGridContainer-grid1');
expect(gridContainerElm.id).toBe('grid1');
expect(footerContainerElm).toBeTruthy();
expect(rightFooterElm).toBeTruthy();
expect(leftFooterElm).toBeTruthy();
expect(component.gridOptions.customFooterOptions!.leftFooterText).toBe('1 items selected');
expect(leftFooterElm.innerHTML).toContain('1 items selected');
});

it('should display row selection count in French on the left side footer section after triggering "onSelectedRowsChanged" event when using "fr" as locale', () => {
const mockColDefs = [{ id: 'name', field: 'name', editor: undefined, internalColumnEditor: {} }];

translate.use('fr');
component.gridOptions = {
enablePagination: false,
enableTranslate: true,
showCustomFooter: true,
enableCheckboxSelector: true,
} as GridOption;
fixture.detectChanges();
component.columnDefinitions = mockColDefs;
component.grid.setSelectionModel(new Slick.CellSelectionModel());
component.grid.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [] });
fixture.detectChanges();

const gridContainerElm = document.querySelector('.slickgrid-container') as HTMLDivElement;
const gridPaneElm = document.querySelector('.gridPane') as HTMLDivElement;
const footerContainerElm = document.querySelector('div.slick-custom-footer') as HTMLDivElement;
let leftFooterElm = document.querySelector('div.slick-custom-footer > div.left-footer') as HTMLSpanElement;
const rightFooterElm = document.querySelector('div.slick-custom-footer > div.metrics') as HTMLSpanElement;

expect(gridPaneElm.id).toBe('slickGridContainer-grid1');
expect(gridContainerElm.id).toBe('grid1');
expect(footerContainerElm).toBeTruthy();
expect(rightFooterElm).toBeTruthy();
expect(leftFooterElm).toBeTruthy();
expect(component.gridOptions.customFooterOptions!.leftFooterText).toBe('1 éléments sélectionnés');
expect(leftFooterElm.innerHTML).toContain('1 éléments sélectionnés');

component.grid.onSelectedRowsChanged.notify({ rows: [1, 2, 3, 4, 5], previousSelectedRows: [] });
component.gridOptions = { enablePagination: false, resizeByContentOnlyOnFirstLoad: true, showCustomFooter: true, autoFitColumnsOnFirstLoad: false, enableAutoSizeColumns: false, enableAutoResizeColumnsByCellContent: true } as GridOption;
component.dataset = mockDataset;
fixture.detectChanges();
leftFooterElm = document.querySelector('div.slick-custom-footer > div.left-footer') as HTMLSpanElement;
component.dataView.onSetItemsCalled.notify({ idProperty: 'id', itemCount: 1 });

expect(component.gridOptions.customFooterOptions!.leftFooterText).toBe('5 éléments sélectionnés');
expect(leftFooterElm.innerHTML).toContain('5 éléments sélectionnés');
setTimeout(() => {
expect(resizeContentSpy).toHaveBeenCalledWith(false);
done();
}, 10);
});

it('should not not display row selection count after triggering "onSelectedRowsChanged" event when "hideRowSelectionCount" is set to True', () => {
const mockColDefs = [{ id: 'name', field: 'name', editor: undefined, internalColumnEditor: {} }];

component.gridId = 'grid1';
component.gridOptions = {
enablePagination: false,
showCustomFooter: true,
enableCheckboxSelector: true,
customFooterOptions: {
hideRowSelectionCount: true
}
} as GridOption;
fixture.detectChanges();
component.columnDefinitions = mockColDefs;
component.grid.setSelectionModel(new Slick.CellSelectionModel());
component.grid.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [] });
fixture.detectChanges();

const gridContainerElm = document.querySelector('.slickgrid-container') as HTMLDivElement;
const gridPaneElm = document.querySelector('.gridPane') as HTMLDivElement;
const footerContainerElm = document.querySelector('div.slick-custom-footer') as HTMLDivElement;
const leftFooterElm = document.querySelector('div.slick-custom-footer > div.left-footer') as HTMLSpanElement;
const rightFooterElm = document.querySelector('div.slick-custom-footer > div.metrics') as HTMLSpanElement;

expect(gridPaneElm.id).toBe('slickGridContainer-grid1');
expect(gridContainerElm.id).toBe('grid1');
expect(footerContainerElm).toBeTruthy();
expect(rightFooterElm).toBeTruthy();
expect(leftFooterElm).toBeTruthy();
expect(component.gridOptions.customFooterOptions!.leftFooterText).toBeFalsy();
expect(leftFooterElm.innerHTML).toBeFalsy();
describe('Custom Footer', () => {
it('should display 1 items selected on the left side footer section after triggering "onSelectedRowsChanged" event', () => {
const mockColDefs = [{ id: 'name', field: 'name', editor: undefined, internalColumnEditor: {} }];

component.gridId = 'grid1';
component.gridOptions = {
enablePagination: false,
showCustomFooter: true,
enableCheckboxSelector: true,
customFooterOptions: {
hideRowSelectionCount: false
}
} as GridOption;
fixture.detectChanges();
component.columnDefinitions = mockColDefs;
component.grid.setSelectionModel(new Slick.CellSelectionModel());
component.grid.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [] });
fixture.detectChanges();

const gridContainerElm = document.querySelector('.slickgrid-container') as HTMLDivElement;
const gridPaneElm = document.querySelector('.gridPane') as HTMLDivElement;
const footerContainerElm = document.querySelector('div.slick-custom-footer') as HTMLDivElement;
const leftFooterElm = document.querySelector('div.slick-custom-footer > div.left-footer') as HTMLSpanElement;
const rightFooterElm = document.querySelector('div.slick-custom-footer > div.metrics') as HTMLSpanElement;

expect(gridPaneElm.id).toBe('slickGridContainer-grid1');
expect(gridContainerElm.id).toBe('grid1');
expect(footerContainerElm).toBeTruthy();
expect(rightFooterElm).toBeTruthy();
expect(leftFooterElm).toBeTruthy();
expect(component.gridOptions.customFooterOptions!.leftFooterText).toBe('1 items selected');
expect(leftFooterElm.innerHTML).toContain('1 items selected');
});

it('should display row selection count in French on the left side footer section after triggering "onSelectedRowsChanged" event when using "fr" as locale', () => {
const mockColDefs = [{ id: 'name', field: 'name', editor: undefined, internalColumnEditor: {} }];

translate.use('fr');
component.gridOptions = {
enablePagination: false,
enableTranslate: true,
showCustomFooter: true,
enableCheckboxSelector: true,
} as GridOption;
fixture.detectChanges();
component.columnDefinitions = mockColDefs;
component.grid.setSelectionModel(new Slick.CellSelectionModel());
component.grid.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [] });
fixture.detectChanges();

const gridContainerElm = document.querySelector('.slickgrid-container') as HTMLDivElement;
const gridPaneElm = document.querySelector('.gridPane') as HTMLDivElement;
const footerContainerElm = document.querySelector('div.slick-custom-footer') as HTMLDivElement;
let leftFooterElm = document.querySelector('div.slick-custom-footer > div.left-footer') as HTMLSpanElement;
const rightFooterElm = document.querySelector('div.slick-custom-footer > div.metrics') as HTMLSpanElement;

expect(gridPaneElm.id).toBe('slickGridContainer-grid1');
expect(gridContainerElm.id).toBe('grid1');
expect(footerContainerElm).toBeTruthy();
expect(rightFooterElm).toBeTruthy();
expect(leftFooterElm).toBeTruthy();
expect(component.gridOptions.customFooterOptions!.leftFooterText).toBe('1 éléments sélectionnés');
expect(leftFooterElm.innerHTML).toContain('1 éléments sélectionnés');

component.grid.onSelectedRowsChanged.notify({ rows: [1, 2, 3, 4, 5], previousSelectedRows: [] });
fixture.detectChanges();
leftFooterElm = document.querySelector('div.slick-custom-footer > div.left-footer') as HTMLSpanElement;

expect(component.gridOptions.customFooterOptions!.leftFooterText).toBe('5 éléments sélectionnés');
expect(leftFooterElm.innerHTML).toContain('5 éléments sélectionnés');
});

it('should not not display row selection count after triggering "onSelectedRowsChanged" event when "hideRowSelectionCount" is set to True', () => {
const mockColDefs = [{ id: 'name', field: 'name', editor: undefined, internalColumnEditor: {} }];

component.gridId = 'grid1';
component.gridOptions = {
enablePagination: false,
showCustomFooter: true,
enableCheckboxSelector: true,
customFooterOptions: {
hideRowSelectionCount: true
}
} as GridOption;
fixture.detectChanges();
component.columnDefinitions = mockColDefs;
component.grid.setSelectionModel(new Slick.CellSelectionModel());
component.grid.onSelectedRowsChanged.notify({ rows: [1], previousSelectedRows: [] });
fixture.detectChanges();

const gridContainerElm = document.querySelector('.slickgrid-container') as HTMLDivElement;
const gridPaneElm = document.querySelector('.gridPane') as HTMLDivElement;
const footerContainerElm = document.querySelector('div.slick-custom-footer') as HTMLDivElement;
const leftFooterElm = document.querySelector('div.slick-custom-footer > div.left-footer') as HTMLSpanElement;
const rightFooterElm = document.querySelector('div.slick-custom-footer > div.metrics') as HTMLSpanElement;

expect(gridPaneElm.id).toBe('slickGridContainer-grid1');
expect(gridContainerElm.id).toBe('grid1');
expect(footerContainerElm).toBeTruthy();
expect(rightFooterElm).toBeTruthy();
expect(leftFooterElm).toBeTruthy();
expect(component.gridOptions.customFooterOptions!.leftFooterText).toBeFalsy();
expect(leftFooterElm.innerHTML).toBeFalsy();
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { isObservable, Observable, Subscription } from 'rxjs';

import { Constants } from '../constants';
import { GlobalGridOptions } from './../global-grid-options';
import { convertParentChildArrayToHierarchicalView, titleCase, unsubscribeAllObservables } from './../services/utilities';
import { emptyElement, titleCase, unsubscribeAllObservables } from './../services/utilities';
import { executeBackendProcessesCallback, onBackendError, refreshBackendDataset } from '../services/backend-utilities';
import {
AngularGridInstance,
Expand Down Expand Up @@ -368,8 +368,9 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
}

emptyGridContainerElm() {
const gridContainerId = this.gridOptions && this.gridOptions.gridContainerId || 'grid1';
$(gridContainerId).empty();
const gridContainerId = this.gridOptions?.gridContainerId ?? 'grid1';
const gridContainerElm = document.querySelector(gridContainerId);
emptyElement(gridContainerElm);
}

/** Dispatch of Custom Event, which by default will bubble & is cancelable */
Expand Down Expand Up @@ -658,7 +659,7 @@ export class AngularSlickgridComponent implements AfterViewInit, OnDestroy, OnIn
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.resizer.resizeColumnsByCellContent(true), 10);
setTimeout(() => this.resizer.resizeColumnsByCellContent(!this.gridOptions?.resizeByContentOnlyOnFirstLoad), 10);
}
});

Expand Down
1 change: 1 addition & 0 deletions src/app/modules/angular-slickgrid/global-grid-options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,7 @@ export const GlobalGridOptions: Partial<GridOption> = {
rowHeight: 35,
topPanelHeight: 35,
translationNamespaceSeparator: ':',
resizeByContentOnlyOnFirstLoad: true,
resizeAlwaysRecalculateColumnWidth: false,
resizeCellCharWidthInPx: 7.8,
resizeCellPaddingWidthInPx: 14,
Expand Down
14 changes: 11 additions & 3 deletions src/app/modules/angular-slickgrid/models/gridOption.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -438,19 +438,27 @@ 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;

/**
Expand Down
Loading

0 comments on commit 135771e

Please sign in to comment.