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
14 changes: 10 additions & 4 deletions src/app/modules/angular-slickgrid/models/filter.interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,15 +20,21 @@ export interface Filter {
/** SlickGrid grid object */
grid: any;

/** Array of defined search terms to pre-load */
searchTerms?: SearchTerm[];
/** The default search operator for the filter when not provided */
defaultOperator?: OperatorString | OperatorType;

/** The search operator for the filter */
operator: OperatorType | OperatorString;

/** You can use "params" to pass any types of arguments to your Filter */
/** You can use "params" to pass any generic arguments to your Filter */
params?: any | any[];

/** Array of defined search terms to pre-load */
searchTerms?: SearchTerm[];

// --
// public functions

/** Filter class initialization, executed by the FilterService right after creating the Filter */
init: (args: FilterArguments, isFilterFirstRender?: boolean) => void;

Expand All @@ -42,5 +48,5 @@ export interface Filter {
getValues?: () => SearchTerm | SearchTerm[] | undefined;

/** Set value(s) on the DOM element */
setValues: (values: SearchTerm | SearchTerm[] | undefined) => void;
setValues: (values: SearchTerm | SearchTerm[] | undefined, operator?: OperatorType | OperatorString) => void;
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ import { of, throwError } from 'rxjs';
import {
BackendService,
Column,
ColumnFilters,
CurrentFilter,
FieldType,
GridMenuItem,
GridOption,
FieldType,
MenuCommandItem,
SlickEventHandler,
} from '../../models';
import { Filters } from '../../filters';
import { FilterService } from '../filter.service';
import { FilterFactory } from '../../filters/filterFactory';
import { SharedService } from '../shared.service';
import { SlickgridConfig, CollectionService } from '../..';
import { CollectionService, SlickgridConfig } from '../../index';
import * as utilities from '../../services/backend-utilities';

const mockRefreshBackendDataset = jest.fn();
Expand Down Expand Up @@ -1361,11 +1362,11 @@ describe('FilterService', () => {
gridStub.onHeaderRowCellRendered.notify(mockArgs1, new Slick.EventData(), gridStub);
gridStub.onHeaderRowCellRendered.notify(mockArgs2, new Slick.EventData(), gridStub);

const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', searchTerms: ['map'] } };
const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', operator: 'Contains', searchTerms: ['map'] } };
service.updateFilters([{ columnId: 'file', operator: '', searchTerms: ['map'] }], true, true, true);
const output = service.customLocalFilter(mockItem1, { dataView: dataViewStub, grid: gridStub, columnFilters });

expect(spyRxjs).toHaveBeenCalledWith([{ columnId: 'file', searchTerms: ['map',] }]);
expect(spyRxjs).toHaveBeenCalledWith([{ columnId: 'file', operator: 'Contains', searchTerms: ['map',] }]);
expect(output).toBe(true);
expect(preFilterSpy).toHaveBeenCalledWith(dataset, columnFilters);
expect(preFilterSpy).toHaveReturnedWith([21, 4, 5]);
Expand All @@ -1385,11 +1386,11 @@ describe('FilterService', () => {
gridStub.onHeaderRowCellRendered.notify(mockArgs1, new Slick.EventData(), gridStub);
gridStub.onHeaderRowCellRendered.notify(mockArgs2, new Slick.EventData(), gridStub);

const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', searchTerms: ['map'] } };
const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', operator: 'Contains', searchTerms: ['map'] } };
service.updateFilters([{ columnId: 'file', operator: '', searchTerms: ['map'] }], true, true, true);
const output = service.customLocalFilter(mockItem1, { dataView: dataViewStub, grid: gridStub, columnFilters });

expect(spyRxjs).toHaveBeenCalledWith([{ columnId: 'file', searchTerms: ['map',] }]);
expect(spyRxjs).toHaveBeenCalledWith([{ columnId: 'file', operator: 'Contains', searchTerms: ['map',] }]);
expect(output).toBe(false);
expect(preFilterSpy).toHaveBeenCalledWith(dataset, columnFilters);
expect(preFilterSpy).toHaveReturnedWith([21, 4, 5]);
Expand All @@ -1409,13 +1410,13 @@ describe('FilterService', () => {
gridStub.onHeaderRowCellRendered.notify(mockArgs1, new Slick.EventData(), gridStub);
gridStub.onHeaderRowCellRendered.notify(mockArgs2, new Slick.EventData(), gridStub);

const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', searchTerms: ['unknown'] } };
const columnFilters = { file: { columnDef: mockColumn1, columnId: 'file', searchTerms: ['unknown'] } } as ColumnFilters;
service.updateFilters([{ columnId: 'file', operator: '', searchTerms: ['unknown'] }], true, true, true);
const output = service.customLocalFilter(mockItem1, { dataView: dataViewStub, grid: gridStub, columnFilters });

expect(spyRxjs).toHaveBeenCalledWith([{ columnId: 'file', searchTerms: ['unknown',] }]);
expect(spyRxjs).toHaveBeenCalledWith([{ columnId: 'file', operator: 'Contains', searchTerms: ['unknown',] }]);
expect(output).toBe(false);
expect(preFilterSpy).toHaveBeenCalledWith(dataset, columnFilters);
expect(preFilterSpy).toHaveBeenCalledWith(dataset, { ...columnFilters, file: { ...columnFilters.file, operator: 'Contains' } }); // it will use Contains by default
expect(preFilterSpy).toHaveReturnedWith([]);
});
});
Expand Down
15 changes: 7 additions & 8 deletions src/app/modules/angular-slickgrid/services/filter.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
SlickEventHandler,
} from './../models/index';
import { executeBackendCallback, refreshBackendDataset } from './backend-utilities';
import { getDescendantProperty } from './utilities';
import { getDescendantProperty, mapOperatorByFieldType } from './utilities';
import { FilterConditions } from './../filter-conditions';
import { FilterFactory } from '../filters/filterFactory';
import { SharedService } from './shared.service';
Expand All @@ -43,7 +43,7 @@ export class FilterService {
private _eventHandler: SlickEventHandler;
private _isFilterFirstRender = true;
private _firstColumnIdRendered = '';
private _filtersMetadata: any[] = [];
protected _filtersMetadata: Array<Filter> = [];
private _columnFilters: ColumnFilters = {};
private _grid: any;
private _onSearchChange: SlickEvent | null;
Expand Down Expand Up @@ -130,7 +130,7 @@ export class FilterService {
if (Array.isArray(this._filtersMetadata)) {
this._filtersMetadata.forEach((filter) => {
if (filter && filter.destroy) {
filter.destroy(true);
filter.destroy();
}
});
}
Expand Down Expand Up @@ -228,7 +228,7 @@ export class FilterService {
}

// find the filter object and call its clear method with true (the argument tells the method it was called by a clear filter)
const colFilter: Filter = this._filtersMetadata.find((filter: Filter) => filter.columnDef.id === columnId);
const colFilter: Filter | undefined = this._filtersMetadata.find((filter: Filter) => filter.columnDef.id === columnId);
if (colFilter && colFilter.clear) {
colFilter.clear(true);
}
Expand Down Expand Up @@ -830,6 +830,7 @@ export class FilterService {
const searchTerms = (args.searchTerms && Array.isArray(args.searchTerms)) ? args.searchTerms : (searchTerm ? [searchTerm] : undefined);
const columnDef = args.columnDef || null;
const columnId = columnDef && columnDef.id || '';
const fieldType = columnDef && columnDef.filter && columnDef.filter.type || columnDef && columnDef.type || FieldType.string;
const operator = args.operator || undefined;
const hasSearchTerms = searchTerms && Array.isArray(searchTerms);
const termsCount = hasSearchTerms && searchTerms && searchTerms.length;
Expand All @@ -847,9 +848,7 @@ export class FilterService {
columnDef,
searchTerms,
};
if (operator) {
colFilter.operator = operator;
}
colFilter.operator = operator || mapOperatorByFieldType(fieldType);
this._columnFilters[colId] = colFilter;
}
}
Expand All @@ -868,7 +867,7 @@ export class FilterService {
columnId,
columnDef,
columnFilters: this._columnFilters,
operator,
operator: operator || mapOperatorByFieldType(fieldType),
searchTerms,
grid: this._grid
}, eventData);
Expand Down
2 changes: 1 addition & 1 deletion test/cypress/integration/example05.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -563,7 +563,7 @@ describe('Example 5 - OData Grid', () => {

cy.window().then((win) => {
expect(win.console.log).to.have.callCount(2);
expect(win.console.log).to.be.calledWith('Client sample, Grid State changed:: ', { newValues: [{ columnId: 'name', searchTerms: ['x'] }], type: 'filter' });
expect(win.console.log).to.be.calledWith('Client sample, Grid State changed:: ', { newValues: [{ columnId: 'name', operator: 'Contains', searchTerms: ['x'] }], type: 'filter' });
expect(win.console.log).to.be.calledWith('Client sample, Grid State changed:: ', { newValues: { pageNumber: 1, pageSize: 10 }, type: 'pagination' });
});
});
Expand Down
2 changes: 1 addition & 1 deletion test/cypress/integration/example08.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ describe('Example 8 - Header Menu Plugin', () => {
cy.get('#grid8')
.find('.slick-row .slick-cell:nth(2)')
.each($row => {
expect(+$row.text()).to.be.greaterThan(80);
expect(+$row.text()).to.be.greaterThan(60);
});
});

Expand Down
6 changes: 3 additions & 3 deletions test/cypress/integration/example10.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -595,7 +595,7 @@ describe('Example 10 - Multiple Grids with Row Selection', () => {

cy.window().then((win) => {
expect(win.console.log).to.be.calledWith("Grid State changed:: ", { newValues: { gridRowIndexes: [0, 1], dataContextIds: [3, 12, 13, 522, 1], filteredDataContextIds: [3, 13] }, type: 'rowSelection' });
expect(win.console.log).to.be.calledWith("Grid State changed:: ", { newValues: [{ columnId: 'title', searchTerms: ['3'] }], type: 'filter' });
expect(win.console.log).to.be.calledWith("Grid State changed:: ", { newValues: [{ columnId: 'title', operator: 'Contains', searchTerms: ['3'] }], type: 'filter' });
});
});

Expand Down Expand Up @@ -678,7 +678,7 @@ describe('Example 10 - Multiple Grids with Row Selection', () => {
cy.window().then((win) => {
expect(win.console.log).to.have.callCount(4);
expect(win.console.log).to.be.calledWith("Grid State changed:: ", { newValues: { gridRowIndexes: [0, 1], dataContextIds: [3, 12, 13, 522, 1], filteredDataContextIds: [3, 13] }, type: 'rowSelection' });
expect(win.console.log).to.be.calledWith("Grid State changed:: ", { newValues: [{ columnId: 'title', searchTerms: ['3'] }], type: 'filter' });
expect(win.console.log).to.be.calledWith("Grid State changed:: ", { newValues: [{ columnId: 'title', operator: 'Contains', searchTerms: ['3'] }], type: 'filter' });
});
});

Expand Down Expand Up @@ -755,7 +755,7 @@ describe('Example 10 - Multiple Grids with Row Selection', () => {
cy.window().then((win) => {
expect(win.console.log).to.have.callCount(4);
expect(win.console.log).to.be.calledWith("Grid State changed:: ", { newValues: { gridRowIndexes: [0, 1], dataContextIds: [3, 12, 13, 522, 1], filteredDataContextIds: [3, 13] }, type: 'rowSelection' });
expect(win.console.log).to.be.calledWith("Grid State changed:: ", { newValues: [{ columnId: 'title', searchTerms: ['3'] }], type: 'filter' });
expect(win.console.log).to.be.calledWith("Grid State changed:: ", { newValues: [{ columnId: 'title', operator: 'Contains', searchTerms: ['3'] }], type: 'filter' });
});
});
});
Expand Down