Skip to content
This repository was archived by the owner on Jun 1, 2025. It is now read-only.
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
2 changes: 1 addition & 1 deletion src/app/examples/grid-editor.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ export class GridEditorComponent implements OnInit {
required: true,
validator: myCustomTitleValidator, // use a custom validator
},
sortable: true, minWidth: 100, filterable: true, params: { useFormatterOuputToFilter: true }
sortable: true, minWidth: 100, filterable: true,
};

// you can dynamically add your column to your column definitions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ const extensionContextMenuStub = {
...extensionStub,
translateContextMenu: jest.fn()
};
const extensionHeaderButtonStub = {
...extensionStub,
translateHeaderMenu: jest.fn()
};
const extensionHeaderMenuStub = {
...extensionStub,
translateHeaderMenu: jest.fn()
Expand Down Expand Up @@ -92,7 +96,7 @@ describe('ExtensionService', () => {
{ provide: DraggableGroupingExtension, useValue: extensionStub },
{ provide: GridMenuExtension, useValue: extensionGridMenuStub },
{ provide: GroupItemMetaProviderExtension, useValue: extensionGroupItemMetaStub },
{ provide: HeaderButtonExtension, useValue: extensionStub },
{ provide: HeaderButtonExtension, useValue: extensionHeaderButtonStub },
{ provide: HeaderMenuExtension, useValue: extensionHeaderMenuStub },
{ provide: RowDetailViewExtension, useValue: extensionStub },
{ provide: RowMoveManagerExtension, useValue: extensionStub },
Expand Down Expand Up @@ -378,7 +382,7 @@ describe('ExtensionService', () => {

expect(gridSpy).toHaveBeenCalled();
expect(extSpy).toHaveBeenCalled();
expect(output).toEqual({ name: ExtensionName.headerButton, addon: instanceMock, instance: instanceMock, class: extensionStub } as ExtensionModel);
expect(output).toEqual({ name: ExtensionName.headerButton, addon: instanceMock, instance: instanceMock, class: extensionHeaderButtonStub } as ExtensionModel);
});

it('should register the HeaderMenu addon when "enableHeaderMenu" is set in the grid options', () => {
Expand Down Expand Up @@ -632,18 +636,18 @@ describe('ExtensionService', () => {

it(`should call "setColumns" with the collection provided as argument but NOT override "allColumns" on the Shared Service
when collection provided is smaller than "allColumns" that already exists`, () => {
const columnsMock = [
{ id: 'field1', field: 'field1', nameKey: 'HELLO' }
] as Column[];
jest.spyOn(SharedService.prototype, 'grid', 'get').mockReturnValue(gridStub);
const spyAllCols = jest.spyOn(SharedService.prototype, 'allColumns', 'set');
const setColumnsSpy = jest.spyOn(gridStub, 'setColumns');
const columnsMock = [
{ id: 'field1', field: 'field1', nameKey: 'HELLO' }
] as Column[];
jest.spyOn(SharedService.prototype, 'grid', 'get').mockReturnValue(gridStub);
const spyAllCols = jest.spyOn(SharedService.prototype, 'allColumns', 'set');
const setColumnsSpy = jest.spyOn(gridStub, 'setColumns');

service.renderColumnHeaders(columnsMock);
service.renderColumnHeaders(columnsMock);

expect(setColumnsSpy).toHaveBeenCalledWith(columnsMock);
expect(spyAllCols).not.toHaveBeenCalled();
});
expect(setColumnsSpy).toHaveBeenCalledWith(columnsMock);
expect(spyAllCols).not.toHaveBeenCalled();
});

it('should re-register the Column Picker when enable and method is called with new column definition collection provided as argument', () => {
const instanceMock = { onColumnsChanged: jest.fn() };
Expand Down Expand Up @@ -698,6 +702,66 @@ describe('ExtensionService', () => {
expect(spyAllCols).toHaveBeenCalledWith(columnsMock);
expect(setColumnsSpy).toHaveBeenCalledWith(columnsMock);
});

it('should re-register the Header Button when enable and method is called with new column definition collection provided as argument', () => {
const instanceMock = { onColumnsChanged: jest.fn() };
const extensionMock = { name: ExtensionName.headerButton, addon: null, instance: null, class: null } as ExtensionModel;
const expectedExtension = { name: ExtensionName.headerButton, instance: instanceMock as unknown, class: null } as ExtensionModel;
const gridOptionsMock = { enableHeaderButton: true } as GridOption;
const columnsMock = [
{ id: 'field1', field: 'field1', nameKey: 'HELLO' },
{ id: 'field2', field: 'field2', nameKey: 'WORLD' }
] as Column[];

jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue(gridOptionsMock);
jest.spyOn(SharedService.prototype, 'grid', 'get').mockReturnValue(gridStub);
const spyGetExt = jest.spyOn(service, 'getExtensionByName').mockReturnValue(extensionMock);
const spyGmDispose = jest.spyOn(extensionHeaderButtonStub, 'dispose');
const spyGmRegister = jest.spyOn(extensionHeaderButtonStub, 'register').mockReturnValue(instanceMock);
const spyAllCols = jest.spyOn(SharedService.prototype, 'allColumns', 'set');
const setColumnsSpy = jest.spyOn(gridStub, 'setColumns');

service.renderColumnHeaders(columnsMock);

expect(expectedExtension).toEqual(expectedExtension);
expect(spyGetExt).toHaveBeenCalled();
expect(expectedExtension).toEqual(expectedExtension);
expect(spyGetExt).toHaveBeenCalled();
expect(spyGmDispose).toHaveBeenCalled();
expect(spyGmRegister).toHaveBeenCalled();
expect(spyAllCols).toHaveBeenCalledWith(columnsMock);
expect(setColumnsSpy).toHaveBeenCalledWith(columnsMock);
});

it('should re-register the Header Menu when enable and method is called with new column definition collection provided as argument', () => {
const instanceMock = { onColumnsChanged: jest.fn() };
const extensionMock = { name: ExtensionName.headerMenu, addon: null, instance: null, class: null } as ExtensionModel;
const expectedExtension = { name: ExtensionName.headerMenu, instance: instanceMock as unknown, class: null } as ExtensionModel;
const gridOptionsMock = { enableHeaderMenu: true } as GridOption;
const columnsMock = [
{ id: 'field1', field: 'field1', nameKey: 'HELLO' },
{ id: 'field2', field: 'field2', nameKey: 'WORLD' }
] as Column[];

jest.spyOn(SharedService.prototype, 'gridOptions', 'get').mockReturnValue(gridOptionsMock);
jest.spyOn(SharedService.prototype, 'grid', 'get').mockReturnValue(gridStub);
const spyGetExt = jest.spyOn(service, 'getExtensionByName').mockReturnValue(extensionMock);
const spyGmDispose = jest.spyOn(extensionHeaderMenuStub, 'dispose');
const spyGmRegister = jest.spyOn(extensionHeaderMenuStub, 'register').mockReturnValue(instanceMock);
const spyAllCols = jest.spyOn(SharedService.prototype, 'allColumns', 'set');
const setColumnsSpy = jest.spyOn(gridStub, 'setColumns');

service.renderColumnHeaders(columnsMock);

expect(expectedExtension).toEqual(expectedExtension);
expect(spyGetExt).toHaveBeenCalled();
expect(expectedExtension).toEqual(expectedExtension);
expect(spyGetExt).toHaveBeenCalled();
expect(spyGmDispose).toHaveBeenCalled();
expect(spyGmRegister).toHaveBeenCalled();
expect(spyAllCols).toHaveBeenCalledWith(columnsMock);
expect(setColumnsSpy).toHaveBeenCalledWith(columnsMock);
});
});
});

Expand All @@ -715,7 +779,7 @@ describe('ExtensionService', () => {
extensionStub as unknown as DraggableGroupingExtension,
extensionGridMenuStub as unknown as GridMenuExtension,
extensionGroupItemMetaStub as unknown as GroupItemMetaProviderExtension,
extensionStub as unknown as HeaderButtonExtension,
extensionHeaderButtonStub as unknown as HeaderButtonExtension,
extensionHeaderMenuStub as unknown as HeaderMenuExtension,
extensionStub as unknown as RowDetailViewExtension,
extensionStub as unknown as RowMoveManagerExtension,
Expand Down
45 changes: 29 additions & 16 deletions src/app/modules/angular-slickgrid/services/extension.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { Injectable, Optional } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';
import {
Column,
Extension,
ExtensionList,
ExtensionModel,
ExtensionName,
Expand Down Expand Up @@ -418,26 +419,24 @@ export class ExtensionService {
this.sharedService.grid.setColumns(collection);
}

// dispose of previous Column Picker instance, then re-register it and don't forget to overwrite previous instance ref
// recreate the Column Picker when enabled
if (this.sharedService.gridOptions.enableColumnPicker) {
this.columnPickerExtension.dispose();
const instance = this.columnPickerExtension.register();
const extension = this.getExtensionByName(ExtensionName.columnPicker);
if (extension) {
extension.addon = instance;
extension.instance = instance;
}
this.recreateExternalAddon(this.columnPickerExtension, ExtensionName.columnPicker);
}

// dispose of previous Grid Menu instance, then re-register it and don't forget to overwrite previous instance ref
// recreate the Grid Menu when enabled
if (this.sharedService.gridOptions.enableGridMenu) {
this.gridMenuExtension.dispose();
const instance = this.gridMenuExtension.register();
const extension = this.getExtensionByName(ExtensionName.gridMenu);
if (extension) {
extension.addon = instance;
extension.instance = instance;
}
this.recreateExternalAddon(this.gridMenuExtension, ExtensionName.gridMenu);
}

// recreate the Header Button when enabled
if (this.sharedService.gridOptions.enableHeaderButton) {
this.recreateExternalAddon(this.headerButtonExtension, ExtensionName.headerButton);
}

// recreate the Header Menu when enabled
if (this.sharedService.gridOptions.enableHeaderMenu) {
this.recreateExternalAddon(this.headerMenuExtension, ExtensionName.headerMenu);
}
}

Expand All @@ -456,6 +455,20 @@ export class ExtensionService {
return undefined;
}

/**
* Dispose of previous extension/addon instance, then re-register it and don't forget to overwrite previous instance ref
* @param extensionName
*/
private recreateExternalAddon(externalExtension: Extension, extensionName: ExtensionName) {
externalExtension.dispose();
const instance = externalExtension.register();
const extension = this.getExtensionByName(extensionName);
if (extension) {
extension.addon = instance;
extension.instance = instance;
}
}

/** Translate an array of items from an input key and assign translated value to the output key */
private translateItems(items: any[], inputKey: string, outputKey: string) {
if (this.sharedService.gridOptions && this.sharedService.gridOptions.enableTranslate && (!this.translate || !this.translate.instant)) {
Expand Down
27 changes: 27 additions & 0 deletions test/cypress/integration/example03.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,33 @@ describe('Example 3 - Grid with Editors', () => {
.scrollTo('top');
});

it('should be able to filter and search "Task 2222" in the new column and expect only 1 row showing in the grid', () => {
cy.get('input.search-filter.filter-title1')
.type('Task 2222', { force: true })
.should('have.value', 'Task 2222');

cy.get('.slick-row').should('have.length', 1);
cy.get(`[style="top:${GRID_ROW_HEIGHT * 0}px"] > .slick-cell:nth(2)`).should('contain', 'Task 2222');
});

it('should hover over the last "Title" column and click on "Clear Filter" and expect grid to have all rows shown', () => {
cy.get('.slick-header-column:nth-child(14)')
.first()
.trigger('mouseover')
.children('.slick-header-menubutton')
.invoke('show')
.click();

cy.get('.slick-header-menu')
.should('be.visible')
.children('.slick-header-menuitem:nth-child(4)')
.children('.slick-header-menucontent')
.should('contain', 'Remove Filter')
.click();

cy.get('.slick-row').should('have.length.greaterThan', 1);
});

it('should be able to dynamically remove last 2 added Title columns', () => {
cy.get('[data-test=remove-title-column]')
.click()
Expand Down
2 changes: 1 addition & 1 deletion test/cypress/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
"author": "Ghislain B.",
"license": "MIT",
"devDependencies": {
"cypress": "^6.3.0",
"cypress": "^6.4.0",
"mocha": "^8.2.1",
"mochawesome": "^6.2.1"
}
Expand Down