Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(resizer): remove delay to call resize by content to avoid flickering #341

Merged
merged 1 commit into from
May 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions packages/common/src/services/__tests__/gridState.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -201,11 +201,40 @@ describe('GridStateService', () => {
jest.spyOn(SharedService.prototype, 'allColumns', 'get').mockReturnValue(allColumnsMock);
const setColsSpy = jest.spyOn(gridStub, 'setColumns');
const autoSizeSpy = jest.spyOn(gridStub, 'autosizeColumns');
const pubSubSpy = jest.spyOn(mockPubSub, 'publish');

service.changeColumnsArrangement(presetColumnsMock);

expect(setColsSpy).toHaveBeenCalledWith([rowCheckboxColumnMock, ...columnsWithoutCheckboxMock]);
expect(autoSizeSpy).toHaveBeenCalled();
expect(pubSubSpy).not.toHaveBeenCalledWith('onFullResizeByContentRequested');
});

it('should call the method and expect slickgrid "setColumns" and a pubsub event "onFullResizeByContentRequested" to be called with newest columns when "triggerAutoSizeColumns" is false and "enableAutoResizeColumnsByCellContent" is true', () => {
gridOptionMock.enableAutoResizeColumnsByCellContent = true;
jest.spyOn(SharedService.prototype, 'allColumns', 'get').mockReturnValue(allColumnsMock);
const setColsSpy = jest.spyOn(gridStub, 'setColumns');
const autoSizeSpy = jest.spyOn(gridStub, 'autosizeColumns');
const pubSubSpy = jest.spyOn(mockPubSub, 'publish');

service.changeColumnsArrangement(presetColumnsMock, false);

expect(setColsSpy).toHaveBeenCalledWith([rowCheckboxColumnMock, ...columnsWithoutCheckboxMock]);
expect(autoSizeSpy).not.toHaveBeenCalled();
expect(pubSubSpy).toHaveBeenCalledWith('onFullResizeByContentRequested', { caller: 'GridStateService' });
});

it('should call the method and expect slickgrid "setColumns" and a pubsub event "onFullResizeByContentRequested" to be called with newest columns when "triggerAutoSizeColumns" is false and "enableAutoResizeColumnsByCellContent" is true', () => {
jest.spyOn(SharedService.prototype, 'allColumns', 'get').mockReturnValue(allColumnsMock);
const setColsSpy = jest.spyOn(gridStub, 'setColumns');
const autoSizeSpy = jest.spyOn(gridStub, 'autosizeColumns');
const pubSubSpy = jest.spyOn(mockPubSub, 'publish');

service.changeColumnsArrangement(presetColumnsMock, false, true);

expect(setColsSpy).toHaveBeenCalledWith([rowCheckboxColumnMock, ...columnsWithoutCheckboxMock]);
expect(autoSizeSpy).not.toHaveBeenCalled();
expect(pubSubSpy).toHaveBeenCalledWith('onFullResizeByContentRequested', { caller: 'GridStateService' });
});

it('should call the method and expect only 1 method of slickgrid "setColumns" to be called when we define 2nd argument (triggerAutoSizeColumns) as False', () => {
Expand Down
7 changes: 6 additions & 1 deletion packages/common/src/services/gridState.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,10 +99,13 @@ export class GridStateService {
* Dynamically change the arrangement/distribution of the columns Positions/Visibilities and optionally Widths.
* For a column to have its visibly as hidden, it has to be part of the original list but excluded from the list provided as argument to be considered a hidden field.
* If you are passing columns Width, then you probably don't want to trigger the autosizeColumns (2nd argument to False).
* We could also resize the columns by their content but be aware that you can only trigger 1 type of resize at a time (either the 2nd argument or the 3rd last argument but not both at same time)
* The resize by content could be called by the 3rd argument OR simply by enabling `enableAutoResizeColumnsByCellContent` but again this will only get executed when the 2nd argument is set to false.
* @param {Array<Column>} definedColumns - defined columns
* @param {Boolean} triggerAutoSizeColumns - True by default, do we also want to call the "autosizeColumns()" method to make the columns fit in the grid?
* @param {Boolean} triggerColumnsFullResizeByContent - False by default, do we also want to call full columns resize by their content?
*/
changeColumnsArrangement(definedColumns: CurrentColumn[], triggerAutoSizeColumns = true) {
changeColumnsArrangement(definedColumns: CurrentColumn[], triggerAutoSizeColumns = true, triggerColumnsFullResizeByContent = false) {
if (Array.isArray(definedColumns) && definedColumns.length > 0) {
const gridColumns: Column[] = this.getAssociatedGridColumns(this._grid, definedColumns);

Expand All @@ -126,6 +129,8 @@ export class GridStateService {
// resize the columns to fit the grid canvas
if (triggerAutoSizeColumns) {
this._grid.autosizeColumns();
} else if (triggerColumnsFullResizeByContent || this._gridOptions.enableAutoResizeColumnsByCellContent) {
this.pubSubService.publish('onFullResizeByContentRequested', { caller: 'GridStateService' });
}
}
}
Expand Down
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -1762,32 +1762,26 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', ()
});

describe('resizeColumnsByCellContent method', () => {
it('should call "resizeColumnsByCellContent" when the DataView "onSetItemsCalled" event is triggered and "enableAutoResizeColumnsByCellContent" is set', (done) => {
it('should call "resizeColumnsByCellContent" when the DataView "onSetItemsCalled" event is triggered and "enableAutoResizeColumnsByCellContent" is set', () => {
const resizeContentSpy = jest.spyOn(resizerServiceStub, 'resizeColumnsByCellContent');
jest.spyOn(mockDataView, 'getLength').mockReturnValue(1);

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 });

setTimeout(() => {
expect(resizeContentSpy).toHaveBeenCalledWith(true);
done();
}, 10);
expect(resizeContentSpy).toHaveBeenCalledWith(true);
});

it('should call "resizeColumnsByCellContent" when the DataView "onSetItemsCalled" event is triggered and "enableAutoResizeColumnsByCellContent" and "resizeColumnsByCellContent" are both set', (done) => {
it('should call "resizeColumnsByCellContent" when the DataView "onSetItemsCalled" event is triggered and "enableAutoResizeColumnsByCellContent" and "resizeColumnsByCellContent" are both set', () => {
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);
expect(resizeContentSpy).toHaveBeenCalledWith(false);
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,9 @@ export class SlickVanillaGridBundle {
this.sharedService.dataView = this.dataView;
this.sharedService.slickGrid = this.slickGrid;

// load the resizer service
this.resizerService.init(this.slickGrid, this._gridParentContainerElm);

this.extensionService.bindDifferentExtensions();
this.bindDifferentHooks(this.slickGrid, this._gridOptions, this.dataView);
this._slickgridInitialized = true;
Expand Down Expand Up @@ -620,9 +623,6 @@ export class SlickVanillaGridBundle {
this._isDatasetInitialized = true;
}

// load the resizer service
this.resizerService.init(this.slickGrid, this._gridParentContainerElm);

// user might want to hide the header row on page load but still have `enableFiltering: true`
// if that is the case, we need to hide the headerRow ONLY AFTER all filters got created & dataView exist
if (this._hideHeaderRowAfterPageLoad) {
Expand Down Expand Up @@ -844,9 +844,7 @@ export class SlickVanillaGridBundle {

// when user has resize by content enabled, we'll force a full width calculation since we change our entire dataset
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(!this.gridOptions?.resizeByContentOnlyOnFirstLoad), 10);
this.resizerService.resizeColumnsByCellContent(!this.gridOptions?.resizeByContentOnlyOnFirstLoad);
}
});

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Column, Editors, FieldType, GridOption, PubSubService, SlickGrid, SlickNamespace, } from '@slickgrid-universal/common';
import { Column, Editors, FieldType, GridOption, SlickGrid, SlickNamespace, } from '@slickgrid-universal/common';
import { EventPubSubService } from '../eventPubSub.service';
import { ResizerService } from '../resizer.service';

declare const Slick: SlickNamespace;
Expand Down Expand Up @@ -50,18 +51,12 @@ const gridStub = {
onSort: new Slick.Event(),
} as unknown as SlickGrid;

const pubSubServiceStub = {
publish: jest.fn(),
subscribe: jest.fn(),
unsubscribe: jest.fn(),
unsubscribeAll: jest.fn(),
} as PubSubService;

describe('Resizer Service', () => {
let service: ResizerService;
let divContainer: HTMLDivElement;
let divHeaderElm: HTMLDivElement;
let divViewportElm: HTMLDivElement;
let eventPubSubService: EventPubSubService;
let mockGridOptions: GridOption;

beforeEach(() => {
Expand All @@ -75,7 +70,8 @@ describe('Resizer Service', () => {
divContainer.appendChild(divViewportElm);
document.body.appendChild(divContainer);

service = new ResizerService(pubSubServiceStub);
eventPubSubService = new EventPubSubService(divContainer);
service = new ResizerService(eventPubSubService);
mockGridOptions = {
enableAutoResize: true,
autoResize: {
Expand Down Expand Up @@ -114,7 +110,7 @@ describe('Resizer Service', () => {

it('should call internal event handler subscribe and expect the "onGridBeforeResize" event to be called when addon notify is called', () => {
const handlerSpy = jest.spyOn(service.eventHandler, 'subscribe');
const pubSubSpy = jest.spyOn(pubSubServiceStub, 'publish');
const pubSubSpy = jest.spyOn(eventPubSubService, 'publish');

service.init(gridStub, divContainer);
const instance = service.getAddonInstance();
Expand All @@ -130,7 +126,7 @@ describe('Resizer Service', () => {

it('should call internal event handler subscribe and expect the "onGridAfterResize" event to be called when addon notify is called', () => {
const handlerSpy = jest.spyOn(service.eventHandler, 'subscribe');
const pubSubSpy = jest.spyOn(pubSubServiceStub, 'publish');
const pubSubSpy = jest.spyOn(eventPubSubService, 'publish');

service.init(gridStub, divContainer);
const instance = service.getAddonInstance();
Expand All @@ -146,7 +142,7 @@ describe('Resizer Service', () => {

it('should call "onGridAfterResize" event and expect "resizeColumnsByCellContent" to be called when "enableAutoResizeColumnsByCellContent" is set', () => {
const resizeContentSpy = jest.spyOn(service, 'resizeColumnsByCellContent');
const pubSubSpy = jest.spyOn(pubSubServiceStub, 'publish');
const pubSubSpy = jest.spyOn(eventPubSubService, 'publish');

mockGridOptions.enableAutoResizeColumnsByCellContent = true;
service.init(gridStub, divContainer);
Expand Down Expand Up @@ -309,7 +305,7 @@ describe('Resizer Service', () => {
it('should call the resize and expect first column have a fixed width while other will have a calculated width when resizing by their content', () => {
const setColumnsSpy = jest.spyOn(gridStub, 'setColumns');
const reRenderColumnsSpy = jest.spyOn(gridStub, 'reRenderColumns');
const pubSubSpy = jest.spyOn(pubSubServiceStub, 'publish');
const pubSubSpy = jest.spyOn(eventPubSubService, 'publish');

service.init(gridStub, divContainer);
service.resizeColumnsByCellContent(true);
Expand All @@ -335,7 +331,7 @@ describe('Resizer Service', () => {
it('should call the resize and expect first column have a fixed width while other will have a calculated width when resizing by their content and grid is editable', () => {
const setColumnsSpy = jest.spyOn(gridStub, 'setColumns');
const reRenderColumnsSpy = jest.spyOn(gridStub, 'reRenderColumns');
const pubSubSpy = jest.spyOn(pubSubServiceStub, 'publish');
const pubSubSpy = jest.spyOn(eventPubSubService, 'publish');

mockGridOptions.editable = true;
service.init(gridStub, divContainer);
Expand All @@ -359,6 +355,15 @@ describe('Resizer Service', () => {
readItemCount: 5
});
});

it('should call "resizeColumnsByCellContent" when "onFullResizeByContentRequested" pubsub event is triggered', () => {
const resizeSpy = jest.spyOn(service, 'resizeColumnsByCellContent');

service.init(gridStub, divContainer);
eventPubSubService.publish('onFullResizeByContentRequested', { caller: 'GridStateService' });

expect(resizeSpy).toHaveBeenCalledWith(true);
});
});
});
});
3 changes: 3 additions & 0 deletions packages/vanilla-bundle/src/services/resizer.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,9 @@ export class ResizerService {
this.eventPubSubService.publish('onGridBeforeResize', args);
});
}

// resize by content could be called from the outside by other services via pub/sub event
this.eventPubSubService.subscribe('onFullResizeByContentRequested', () => this.resizeColumnsByCellContent(true));
}
}

Expand Down