Skip to content

Commit 8c10e5a

Browse files
committed
feat(filters): provide method to apply grid filters dynamically
- prior to this change, we could update filters only through "presets", after this change we coud change filters on the fly at any time
1 parent 3f0cef6 commit 8c10e5a

13 files changed

+210
-94
lines changed

src/app/examples/grid-clientside.component.html

+5-8
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,11 @@ <h2>{{title}}</h2>
99
</span>
1010
<button class="btn btn-default btn-sm" (click)="angularGrid.filterService.clearFilters()">Clear Filters</button>
1111
<button class="btn btn-default btn-sm" (click)="angularGrid.sortService.clearSorting()">Clear Sorting</button>
12+
<button class="btn btn-default btn-sm" (click)="setSomeFilters()">Set Some Filters</button>
1213

13-
<angular-slickgrid gridId="grid2"
14-
[columnDefinitions]="columnDefinitions"
15-
[gridOptions]="gridOptions"
16-
[dataset]="dataset"
17-
(onAngularGridCreated)="angularGridReady($event)"
18-
(onGridStateChanged)="gridStateChanged($event)"
19-
(onBeforeGridDestroy)="saveCurrentGridState($event)"
20-
(sgOnRowCountChanged)="refreshMetrics($event.detail.eventData, $event.detail.args)">
14+
<angular-slickgrid gridId="grid2" [columnDefinitions]="columnDefinitions" [gridOptions]="gridOptions"
15+
[dataset]="dataset" (onAngularGridCreated)="angularGridReady($event)"
16+
(onGridStateChanged)="gridStateChanged($event)" (onBeforeGridDestroy)="saveCurrentGridState($event)"
17+
(sgOnRowCountChanged)="refreshMetrics($event.detail.eventData, $event.detail.args)">
2118
</angular-slickgrid>
2219
</div>

src/app/examples/grid-clientside.component.ts

+11-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ import {
1919
function randomBetween(min, max) {
2020
return Math.floor(Math.random() * (max - min + 1) + min);
2121
}
22-
const NB_ITEMS = 500;
22+
const NB_ITEMS = 1000;
2323
const URL_SAMPLE_COLLECTION_DATA = 'assets/data/collection_500_numbers.json';
2424

2525
@Component({
@@ -209,8 +209,8 @@ export class GridClientSideComponent implements OnInit {
209209
const tempDataset = [];
210210
for (let i = startingIndex; i < (startingIndex + itemCount); i++) {
211211
const randomDuration = Math.round(Math.random() * 100);
212-
const randomYear = randomBetween(2000, 2025);
213-
const randomYearShort = randomBetween(10, 25);
212+
const randomYear = randomBetween(2000, 2035);
213+
const randomYearShort = randomBetween(10, 35);
214214
const randomMonth = randomBetween(1, 12);
215215
const randomMonthStr = (randomMonth < 10) ? `0${randomMonth}` : randomMonth;
216216
const randomDay = randomBetween(10, 28);
@@ -249,6 +249,14 @@ export class GridClientSideComponent implements OnInit {
249249
console.log('Client sample, last Grid State:: ', this.angularGrid.gridStateService.getCurrentGridState());
250250
}
251251

252+
setSomeFilters() {
253+
// we can Set Some Filters (or different filters) afterward through the FilterService
254+
this.angularGrid.filterService.updateFilters([
255+
{ columnId: 'duration', searchTerms: [10, 220] },
256+
{ columnId: 'usDateShort', operator: '<', searchTerms: ['4/20/25'] },
257+
]);
258+
}
259+
252260
refreshMetrics(e, args) {
253261
if (args && args.current > 0) {
254262
setTimeout(() => {

src/app/examples/grid-graphql.component.html

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ <h2>{{title}}</h2>
3434
<button class="btn btn-default btn-xs" data-test="goto-last-page" (click)="goToLastPage()">
3535
<i class="fa fa-caret-right fa-lg"></i>
3636
</button>
37+
<button class="btn btn-default btn-xs" (click)="setSomeFilters()">Set Some Filters</button>
3738
</div>
3839
</div>
3940
<div class="col-sm-7">
@@ -45,8 +46,7 @@ <h2>{{title}}</h2>
4546
</div>
4647

4748
<angular-slickgrid gridId="grid6" [gridHeight]="200" [gridWidth]="900" [columnDefinitions]="columnDefinitions"
48-
[gridOptions]="gridOptions" [dataset]="dataset" (onAngularGridCreated)="angularGridReady($event)"
49-
(onGridStateChanged)="gridStateChanged($event)"
50-
(onBeforeGridDestroy)="saveCurrentGridState($event)">
49+
[gridOptions]="gridOptions" [dataset]="dataset" (onAngularGridCreated)="angularGridReady($event)"
50+
(onGridStateChanged)="gridStateChanged($event)" (onBeforeGridDestroy)="saveCurrentGridState($event)">
5151
</angular-slickgrid>
5252
</div>

src/app/examples/grid-graphql.component.ts

+13
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,19 @@ export class GridGraphqlComponent implements OnInit, OnDestroy {
264264
console.log('GraphQL current grid state', this.angularGrid.gridStateService.getCurrentGridState());
265265
}
266266

267+
setSomeFilters() {
268+
const presetLowestDay = moment().add(-2, 'days').format('YYYY-MM-DD');
269+
const presetHighestDay = moment().add(20, 'days').format('YYYY-MM-DD');
270+
271+
// we can Set Some Filters (or different filters) afterward through the FilterService
272+
this.angularGrid.filterService.updateFilters([
273+
{ columnId: 'gender', searchTerms: ['male'], operator: OperatorType.equal },
274+
{ columnId: 'name', searchTerms: ['John Doe'], operator: OperatorType.contains },
275+
{ columnId: 'company', searchTerms: ['xyz'], operator: 'IN' },
276+
{ columnId: 'finish', searchTerms: [presetLowestDay, presetHighestDay], operator: OperatorType.rangeInclusive },
277+
]);
278+
}
279+
267280
switchLanguage() {
268281
this.selectedLanguage = (this.selectedLanguage === 'en') ? 'fr' : 'en';
269282
this.translate.use(this.selectedLanguage);

src/app/examples/grid-odata.component.html

+6-5
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,16 @@ <h2>{{title}}</h2>
2424
<span data-test="radioVersion">
2525
<label class="radio-inline control-label" for="radio2">
2626
<input type="radio" name="inlineRadioOptions" data-test="version2" id="radio2" checked [value]="2"
27-
(change)="setOdataVersion(2)"> 2
27+
(change)="setOdataVersion(2)"> 2
2828
</label>
2929
<label class="radio-inline control-label" for="radio4">
3030
<input type="radio" name="inlineRadioOptions" data-test="version4" id="radio4" [value]="4"
31-
(change)="setOdataVersion(4)"> 4
31+
(change)="setOdataVersion(4)"> 4
3232
</label>
3333
</span>
3434
<label class="checkbox-inline control-label" for="enableCount" style="margin-left: 20px">
3535
<input type="checkbox" id="enableCount" data-test="enable-count" [checked]="isCountEnabled"
36-
(click)="changeCountEnableFlag()">
36+
(click)="changeCountEnableFlag()">
3737
<span style="font-weight: bold">Enable Count</span> (add to OData query)
3838
</label>
3939
</div>
@@ -46,10 +46,11 @@ <h2>{{title}}</h2>
4646
<button class="btn btn-default btn-xs" data-test="goto-last-page" (click)="goToLastPage()">
4747
<i class="fa fa-caret-right fa-lg"></i>
4848
</button>
49+
<button class="btn btn-default btn-xs" (click)="setSomeFilters()">Set Some Filters</button>
4950
</div>
5051

5152
<angular-slickgrid gridId="grid5" [columnDefinitions]="columnDefinitions" [gridOptions]="gridOptions"
52-
[dataset]="dataset" (onGridStateChanged)="gridStateChanged($event)"
53-
(onAngularGridCreated)="angularGridReady($event)">
53+
[dataset]="dataset" (onGridStateChanged)="gridStateChanged($event)"
54+
(onAngularGridCreated)="angularGridReady($event)">
5455
</angular-slickgrid>
5556
</div>

src/app/examples/grid-odata.component.ts

+8
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,14 @@ export class GridOdataComponent implements OnInit {
161161
this.angularGrid.paginationService.goToLastPage();
162162
}
163163

164+
setSomeFilters() {
165+
// we can Set Some Filters (or different filters) afterward through the FilterService
166+
this.angularGrid.filterService.updateFilters([
167+
// { columnId: 'gender', searchTerms: ['male'], operator: OperatorType.equal },
168+
{ columnId: 'name', searchTerms: ['A'], operator: 'a*' },
169+
]);
170+
}
171+
164172
/** This function is only here to mock a WebAPI call (since we are using a JSON file for the demo)
165173
* in your case the getCustomer() should be a WebAPI function returning a Promise
166174
*/

src/app/modules/angular-slickgrid/extensions/gridMenuExtension.ts

+2-46
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { FilterService } from '../services/filter.service';
2121
import { SortService } from '../services/sort.service';
2222
import { castToPromise } from '../services/utilities';
2323
import { SharedService } from '../services/shared.service';
24+
import { refreshBackendDataset } from '../services/backend-utilities';
2425

2526
// using external non-typed js libraries
2627
declare var Slick: any;
@@ -142,58 +143,13 @@ export class GridMenuExtension implements Extension {
142143

143144
/** Refresh the dataset through the Backend Service */
144145
refreshBackendDataset(gridOptions?: GridOption) {
145-
let query = '';
146-
147146
// user can pass new set of grid options which will override current ones
148147
if (gridOptions) {
149148
this.sharedService.gridOptions = { ...this.sharedService.gridOptions, ...gridOptions };
150149
}
151150

152151
const backendApi = this.sharedService.gridOptions.backendServiceApi;
153-
if (!backendApi || !backendApi.service || !backendApi.process) {
154-
throw new Error(`BackendServiceApi requires at least a "process" function and a "service" defined`);
155-
}
156-
157-
if (backendApi.service) {
158-
query = backendApi.service.buildQuery();
159-
}
160-
161-
if (query && query !== '') {
162-
// keep start time & end timestamps & return it after process execution
163-
const startTime = new Date();
164-
165-
if (backendApi.preProcess) {
166-
backendApi.preProcess();
167-
}
168-
169-
// the process could be an Observable (like HttpClient) or a Promise
170-
// in any case, we need to have a Promise so that we can await on it (if an Observable, convert it to Promise)
171-
const observableOrPromise = backendApi.process(query);
172-
173-
castToPromise(observableOrPromise).then((processResult: GraphqlResult | any) => {
174-
const endTime = new Date();
175-
176-
// from the result, call our internal post process to update the Dataset and Pagination info
177-
if (processResult && backendApi && backendApi.internalPostProcess) {
178-
backendApi.internalPostProcess(processResult);
179-
}
180-
181-
// send the response process to the postProcess callback
182-
if (backendApi && backendApi.postProcess) {
183-
if (processResult instanceof Object) {
184-
processResult.metrics = {
185-
startTime,
186-
endTime,
187-
executionTime: endTime.valueOf() - startTime.valueOf(),
188-
totalItemCount: this.sharedService.gridOptions && this.sharedService.gridOptions.pagination && this.sharedService.gridOptions.pagination.totalItems
189-
};
190-
// @deprecated
191-
processResult.statistics = processResult.metrics;
192-
}
193-
backendApi.postProcess(processResult);
194-
}
195-
});
196-
}
152+
refreshBackendDataset(backendApi, this.sharedService.gridOptions);
197153
}
198154

199155
showGridMenu(e) {

src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts

+19-5
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,11 @@ export class CompoundDateFilter implements Filter {
5757
return this._currentDate;
5858
}
5959

60+
/** Getter to know what would be the default operator when none is specified */
61+
get defaultOperator(): OperatorType | OperatorString {
62+
return OperatorType.empty;
63+
}
64+
6065
/** Getter for the Flatpickr Options */
6166
get flatpickrOptions(): FlatpickrOption {
6267
return this._flatpickrOptions || {};
@@ -69,7 +74,7 @@ export class CompoundDateFilter implements Filter {
6974

7075
/** Getter for the Filter Operator */
7176
get operator(): OperatorType | OperatorString {
72-
return this._operator || this.columnFilter.operator || OperatorType.empty;
77+
return this._operator || this.columnFilter.operator || this.defaultOperator;
7378
}
7479

7580
/**
@@ -139,17 +144,26 @@ export class CompoundDateFilter implements Filter {
139144
}
140145
}
141146

142-
/**
143-
* Set value(s) on the DOM element
144-
*/
145-
setValues(values: SearchTerm | SearchTerm[]) {
147+
/** Set value(s) in the DOM element, we can optionally pass an operator and/or trigger a change event */
148+
setValues(values: SearchTerm | SearchTerm[], operator?: OperatorType | OperatorString, triggerChange = false) {
146149
if (this.flatInstance && values && Array.isArray(values)) {
147150
this._currentDate = values[0] as Date;
148151
this.flatInstance.setDate(values[0]);
149152
} else if (this.flatInstance && values && values) {
150153
this._currentDate = values as Date;
151154
this.flatInstance.setDate(values);
152155
}
156+
157+
this.operator = operator || this.defaultOperator;
158+
if (operator && this.$selectOperatorElm) {
159+
this.$selectOperatorElm.val(operator);
160+
}
161+
162+
if (triggerChange) {
163+
this._clearFilterTriggered = false;
164+
this._shouldTriggerQuery = true;
165+
this.onTriggerEvent(new Event('change'));
166+
}
153167
}
154168

155169
//

src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts

+18-2
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,11 @@ export class CompoundInputFilter implements Filter {
4343
return this.columnDef && this.columnDef.filter || {};
4444
}
4545

46+
/** Getter to know what would be the default operator when none is specified */
47+
get defaultOperator(): OperatorType | OperatorString {
48+
return OperatorType.empty;
49+
}
50+
4651
/** Getter of input type (text, number, password) */
4752
get inputType() {
4853
return this._inputType;
@@ -55,7 +60,7 @@ export class CompoundInputFilter implements Filter {
5560

5661
/** Getter of the Operator to use when doing the filter comparing */
5762
get operator(): OperatorType | OperatorString {
58-
return this._operator || OperatorType.empty;
63+
return this._operator || this.defaultOperator;
5964
}
6065

6166
/** Getter of the Operator to use when doing the filter comparing */
@@ -124,10 +129,21 @@ export class CompoundInputFilter implements Filter {
124129
/**
125130
* Set value(s) on the DOM element
126131
*/
127-
setValues(values: SearchTerm[]) {
132+
setValues(values: SearchTerm[], operator?: OperatorType | OperatorString, triggerChange = false) {
128133
if (values && Array.isArray(values)) {
129134
this.$filterInputElm.val(values[0]);
130135
}
136+
137+
this.operator = operator || this.defaultOperator;
138+
if (operator && this.$selectOperatorElm) {
139+
this.$selectOperatorElm.val(operator);
140+
}
141+
142+
if (triggerChange) {
143+
this._clearFilterTriggered = false;
144+
this._shouldTriggerQuery = true;
145+
this.onTriggerEvent(new Event('change'));
146+
}
131147
}
132148

133149
//

src/app/modules/angular-slickgrid/filters/dateRangeFilter.ts

+22-2
Original file line numberDiff line numberDiff line change
@@ -58,14 +58,26 @@ export class DateRangeFilter implements Filter {
5858
return this._currentDates;
5959
}
6060

61+
/** Getter to know what would be the default operator when none is specified */
62+
get defaultOperator(): OperatorType | OperatorString {
63+
return this.gridOptions.defaultFilterRangeOperator || OperatorType.rangeExclusive;
64+
}
65+
6166
/** Getter for the Flatpickr Options */
6267
get flatpickrOptions(): FlatpickrOption {
6368
return this._flatpickrOptions || {};
6469
}
6570

6671
/** Getter of the Operator to use when doing the filter comparing */
6772
get operator(): OperatorType | OperatorString {
68-
return this.columnFilter.operator || this.gridOptions.defaultFilterRangeOperator || OperatorType.rangeExclusive;
73+
return this.columnFilter && this.columnFilter.operator || this.defaultOperator;
74+
}
75+
76+
/** Setter for the filter operator */
77+
set operator(operator: OperatorType | OperatorString) {
78+
if (this.columnFilter) {
79+
this.columnFilter.operator = operator;
80+
}
6981
}
7082

7183
/**
@@ -131,7 +143,7 @@ export class DateRangeFilter implements Filter {
131143
* Set value(s) on the DOM element
132144
* @params searchTerms
133145
*/
134-
setValues(searchTerms: SearchTerm[]) {
146+
setValues(searchTerms: SearchTerm[], operator?: OperatorType | OperatorString, triggerChange = false) {
135147
let pickerValues = [];
136148

137149
// get the picker values, if it's a string with the "..", we'll do the split else we'll use the array of search terms
@@ -145,6 +157,14 @@ export class DateRangeFilter implements Filter {
145157
this._currentDates = pickerValues;
146158
this.flatInstance.setDate(pickerValues);
147159
}
160+
161+
this.operator = operator || this.defaultOperator;
162+
163+
if (triggerChange) {
164+
this._clearFilterTriggered = false;
165+
this._shouldTriggerQuery = true;
166+
this.onTriggerEvent(undefined);
167+
}
148168
}
149169

150170
//

0 commit comments

Comments
 (0)