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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ module.exports = {
```

### Fully Tested with [Jest](https://jestjs.io/) (Unit Tests) - [Cypress](https://www.cypress.io/) (E2E Tests)
Angular-Slickgrid reached **100%** Unit Test Coverage, we are talking about ~10,000 lines of code (+2,600 unit tests) that are now fully tested with [Jest](https://jestjs.io/). There are also over 300 Cypress E2E tests to cover most UI functionalities.
Angular-Slickgrid reached **100%** Unit Test Coverage, we are talking about +10,000 lines of code (+2,700 unit tests) that are now fully tested with [Jest](https://jestjs.io/). There are also over +350 Cypress E2E tests to cover most UI functionalities on nearly all Examples of Angular-Slickgrid.

## Installation
Refer to the **[Wiki - HOWTO Step by Step](https://github.com/ghiscoding/angular-slickgrid/wiki/HOWTO---Step-by-Step)** and/or clone the [Angular-Slickgrid Demos](https://github.com/ghiscoding/angular-slickgrid-demos) repository. Please don't open any issue unless you have followed these steps (from the Wiki), and if any of the steps are incorrect or confusing, then please let me know.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import {
BackendService,
Column,
CurrentFilter,
GridMenuItem,
GridOption,
FieldType,
MenuCommandItem,
SlickEventHandler,
} from '../../models';
import { Filters } from '../../filters';
Expand All @@ -35,6 +37,22 @@ const gridOptionMock = {
preProcess: jest.fn(),
process: jest.fn(),
postProcess: jest.fn(),
},
gridMenu: {
customItems: [{
command: 'clear-filter',
disabled: false,
iconCssClass: 'fa fa-filter mdi mdi-filter-remove-outline',
positionOrder: 50,
title: 'Clear all Filters'
}, {
command: 'toggle-filter',
disabled: false,
hidden: true,
iconCssClass: 'fa fa-random mdi mdi-flip-vertical',
positionOrder: 52,
title: 'Toggle Filter Row'
}]
}
} as GridOption;

Expand Down Expand Up @@ -1125,15 +1143,25 @@ describe('FilterService', () => {
});

it('should disable the Filter Functionality from the Grid Options & toggle the Header Filter row', () => {
const mockColumns = [{ id: 'field1', field: 'field1', width: 100 }, { id: 'field2', field: 'field2', width: 100 }];
const mockColumns = [
{ id: 'field1', field: 'field1', width: 100, header: { menu: { items: [{ command: 'clear-filter' }] } } },
{ id: 'field2', field: 'field2', width: 100, header: { menu: { items: [{ command: 'clear-filter' }] } } }
];
const setOptionSpy = jest.spyOn(gridStub, 'setOptions');
const setHeaderSpy = jest.spyOn(gridStub, 'setHeaderRowVisibility');
const setColsSpy = jest.spyOn(gridStub, 'setColumns');
jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns);
jest.spyOn(SharedService.prototype, 'columnDefinitions', 'get').mockReturnValue(mockColumns)

service.init(gridStub);
service.disableFilterFunctionality();

mockColumns.forEach(col => col.header.menu.items.forEach(item => {
expect((item as MenuCommandItem).hidden).toBeTruthy();
}));
gridOptionMock.gridMenu.customItems.forEach(item => {
expect((item as GridMenuItem).hidden).toBeTruthy();
});
expect(setOptionSpy).toHaveBeenCalledWith({ enableFiltering: false }, false, true);
expect(setHeaderSpy).toHaveBeenCalledWith(false);
expect(setColsSpy).toHaveBeenCalledWith(mockColumns);
Expand All @@ -1143,15 +1171,25 @@ describe('FilterService', () => {
gridOptionMock.enableFiltering = false;
gridOptionMock.showHeaderRow = false;

const mockColumns = [{ id: 'field1', field: 'field1', width: 100 }, { id: 'field2', field: 'field2', width: 100 }];
const mockColumns = [
{ id: 'field1', field: 'field1', width: 100, header: { menu: { items: [{ command: 'clear-filter' }] } } },
{ id: 'field2', field: 'field2', width: 100, header: { menu: { items: [{ command: 'clear-filter' }] } } }
];
const setOptionSpy = jest.spyOn(gridStub, 'setOptions');
const setHeaderSpy = jest.spyOn(gridStub, 'setHeaderRowVisibility');
const setColsSpy = jest.spyOn(gridStub, 'setColumns');
jest.spyOn(gridStub, 'getColumns').mockReturnValue(mockColumns);
jest.spyOn(SharedService.prototype, 'columnDefinitions', 'get').mockReturnValue(mockColumns)

service.init(gridStub);
service.disableFilterFunctionality(false);

mockColumns.forEach(col => col.header.menu.items.forEach(item => {
expect((item as MenuCommandItem).hidden).toBeFalsy();
}));
gridOptionMock.gridMenu.customItems.forEach(item => {
expect((item as GridMenuItem).hidden).toBeFalsy();
});
expect(setOptionSpy).toHaveBeenCalledWith({ enableFiltering: true }, false, true);
expect(setHeaderSpy).toHaveBeenCalledWith(true);
expect(setColsSpy).toHaveBeenCalledWith(mockColumns);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
CurrentSorter,
EmitterType,
FieldType,
GridMenuItem,
GridOption,
MenuCommandItem,
SlickEventHandler,
Expand All @@ -29,6 +30,16 @@ const gridOptionMock = {
preProcess: jest.fn(),
process: jest.fn(),
postProcess: jest.fn(),
},
gridMenu: {
customItems: [{
command: 'clear-sorting',
disabled: false,
hidden: true,
iconCssClass: 'fa fa-unsorted mdi mdi-swap-vertical',
positionOrder: 51,
title: 'Clear all Sorting'
}]
}
} as GridOption;

Expand Down Expand Up @@ -563,11 +574,14 @@ describe('SortService', () => {
expect(clearSpy).toHaveBeenCalled();
expect(unsubscribeSpy).toHaveBeenCalled();
mockColumns.forEach(col => {
expect(col.sortable).toBeFalse();
expect(col.sortable).toBeFalsy();
});
mockColumns.forEach(col => col.header.menu.items.forEach(item => {
expect((item as MenuCommandItem).hidden).toBeTrue();
expect((item as MenuCommandItem).hidden).toBeTruthy();
}));
gridOptionMock.gridMenu.customItems.forEach(item => {
expect((item as GridMenuItem).hidden).toBeTruthy();
});
});

it('should disable Sort functionality when passing True as 1st argument and False as 2nd argument SHOULD NOT trigger an event', () => {
Expand All @@ -581,11 +595,14 @@ describe('SortService', () => {
expect(clearSpy).not.toHaveBeenCalled();
expect(unsubscribeSpy).toHaveBeenCalled();
mockColumns.forEach(col => {
expect(col.sortable).toBeFalse();
expect(col.sortable).toBeFalsy();
});
mockColumns.forEach(col => col.header.menu.items.forEach(item => {
expect((item as MenuCommandItem).hidden).toBeTrue();
expect((item as MenuCommandItem).hidden).toBeTruthy();
}));
gridOptionMock.gridMenu.customItems.forEach(item => {
expect((item as GridMenuItem).hidden).toBeTruthy();
});
});

it('should enable Sort functionality when passing False as 1st argument', (done) => {
Expand All @@ -597,11 +614,14 @@ describe('SortService', () => {
gridStub.onSort.notify({ multiColumnSort: true, sortCols: [], grid: gridStub }, new Slick.EventData(), gridStub);

mockColumns.forEach(col => {
expect(col.sortable).toBeTrue();
expect(col.sortable).toBeTruthy();
});
mockColumns.forEach(col => col.header.menu.items.forEach(item => {
expect((item as MenuCommandItem).hidden).toBeFalse();
expect((item as MenuCommandItem).hidden).toBeFalsy();
}));
gridOptionMock.gridMenu.customItems.forEach(item => {
expect((item as GridMenuItem).hidden).toBeFalsy();
});

setTimeout(() => {
expect(handleSpy).toHaveBeenCalled();
Expand Down
42 changes: 42 additions & 0 deletions src/app/modules/angular-slickgrid/services/filter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -651,8 +651,11 @@ export class FilterService {
if (clearFiltersWhenDisabled && isFilterDisabled) {
this.clearFilters();
}
this.disableAllFilteringCommands(isFilterDisabled);
this._grid.setOptions({ enableFiltering: newShowFilterFlag }, false, true);
this._grid.setHeaderRowVisibility(newShowFilterFlag);
this._gridOptions.enableFiltering = !isFilterDisabled;
this.sharedService.gridOptions = this._gridOptions;

// when displaying header row, we'll call "setColumns" which in terms will recreate the header row filters
this._grid.setColumns(this.sharedService.columnDefinitions);
Expand Down Expand Up @@ -859,6 +862,45 @@ export class FilterService {
}
}

/**
* Loop through all column definitions and do the following thing
* 1. loop through each Header Menu commands and change the "hidden" commands to show/hide depending if it's enabled/disabled
* Also note that we aren't deleting any properties, we just toggle their flags so that we can reloop through at later point in time.
* (if we previously deleted these properties we wouldn't be able to change them back since these properties wouldn't exist anymore, hence why we just hide the commands)
* @param {boolean} isDisabling - are we disabling the filter functionality? Defaults to true
*/
private disableAllFilteringCommands(isDisabling = true): Column[] {
const columnDefinitions = this._grid.getColumns();

// loop through column definition to hide/show header menu commands
columnDefinitions.forEach((col) => {
if (col && col.header && col.header.menu) {
col.header.menu.items.forEach(menuItem => {
if (menuItem && typeof menuItem !== 'string') {
const menuCommand = menuItem.command;
if (menuCommand === 'clear-filter') {
menuItem.hidden = isDisabling;
}
}
});
}
});

// loop through column definition to hide/show grid menu commands
if (this._gridOptions && this._gridOptions.gridMenu && this._gridOptions.gridMenu.customItems) {
this._gridOptions.gridMenu.customItems.forEach((menuItem) => {
if (menuItem && typeof menuItem !== 'string') {
const menuCommand = menuItem.command;
if (menuCommand === 'clear-filter' || menuCommand === 'toggle-filter') {
menuItem.hidden = isDisabling;
}
}
});
}

return columnDefinitions;
}

private updateColumnFilters(searchTerms: SearchTerm[] | undefined, columnDef: any, operator?: OperatorType | OperatorString) {
if (searchTerms && columnDef) {
this._columnFilters[columnDef.id] = {
Expand Down
22 changes: 18 additions & 4 deletions src/app/modules/angular-slickgrid/services/sort.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -206,13 +206,14 @@ export class SortService {
this.clearSorting();
}
this._eventHandler.unsubscribeAll();
updatedColumnDefinitions = this.disableSortingOnAllColumns(true);
updatedColumnDefinitions = this.disableAllSortingCommands(true);
} else {
updatedColumnDefinitions = this.disableSortingOnAllColumns(false);
updatedColumnDefinitions = this.disableAllSortingCommands(false);
const onSortHandler = this._grid.onSort;
this._eventHandler.subscribe(onSortHandler, (e: Event, args: any) => this.handleLocalOnSort(e, args));
}
this._grid.setOptions({ enableSorting: this._gridOptions.enableSorting }, false, true);
this.sharedService.gridOptions = this._gridOptions;

// reset columns so that it recreate the column headers and remove/add the sort icon hints
// basically without this, the sort icon hints were still showing up even after disabling the Sorting
Expand Down Expand Up @@ -527,14 +528,15 @@ export class SortService {
/**
* Loop through all column definitions and do the following 2 things
* 1. disable/enable the "sortable" property of each column
* 2. loop through each Header Menu commands and change the command "hidden" property to enable/disable
* 2. loop through each Header Menu commands and change the "hidden" commands to show/hide depending if it's enabled/disabled
* Also note that we aren't deleting any properties, we just toggle their flags so that we can reloop through at later point in time.
* (if we previously deleted these properties we wouldn't be able to change them back since these properties wouldn't exist anymore, hence why we just hide the commands)
* @param {boolean} isDisabling - are we disabling the sort functionality? Defaults to true
*/
private disableSortingOnAllColumns(isDisabling = true): Column[] {
private disableAllSortingCommands(isDisabling = true): Column[] {
const columnDefinitions = this._grid.getColumns();

// loop through column definition to hide/show header menu commands
columnDefinitions.forEach((col) => {
if (typeof col.sortable !== undefined) {
col.sortable = !isDisabling;
Expand All @@ -551,6 +553,18 @@ export class SortService {
}
});

// loop through column definition to hide/show grid menu commands
if (this._gridOptions && this._gridOptions.gridMenu && this._gridOptions.gridMenu.customItems) {
this._gridOptions.gridMenu.customItems.forEach((menuItem) => {
if (menuItem && typeof menuItem !== 'string') {
const menuCommand = menuItem.command;
if (menuCommand === 'clear-sorting') {
menuItem.hidden = isDisabling;
}
}
});
}

return columnDefinitions;
}
}
Loading