Skip to content

Commit

Permalink
feat(filters): provide method to apply grid filters dynamically
Browse files Browse the repository at this point in the history
- prior to this change, we could update filters only through "presets", after this change we coud change filters on the fly at any time
  • Loading branch information
ghiscoding-SE committed Nov 11, 2019
1 parent 3f0cef6 commit 8c10e5a
Show file tree
Hide file tree
Showing 13 changed files with 210 additions and 94 deletions.
13 changes: 5 additions & 8 deletions src/app/examples/grid-clientside.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,11 @@ <h2>{{title}}</h2>
</span>
<button class="btn btn-default btn-sm" (click)="angularGrid.filterService.clearFilters()">Clear Filters</button>
<button class="btn btn-default btn-sm" (click)="angularGrid.sortService.clearSorting()">Clear Sorting</button>
<button class="btn btn-default btn-sm" (click)="setSomeFilters()">Set Some Filters</button>

<angular-slickgrid gridId="grid2"
[columnDefinitions]="columnDefinitions"
[gridOptions]="gridOptions"
[dataset]="dataset"
(onAngularGridCreated)="angularGridReady($event)"
(onGridStateChanged)="gridStateChanged($event)"
(onBeforeGridDestroy)="saveCurrentGridState($event)"
(sgOnRowCountChanged)="refreshMetrics($event.detail.eventData, $event.detail.args)">
<angular-slickgrid gridId="grid2" [columnDefinitions]="columnDefinitions" [gridOptions]="gridOptions"
[dataset]="dataset" (onAngularGridCreated)="angularGridReady($event)"
(onGridStateChanged)="gridStateChanged($event)" (onBeforeGridDestroy)="saveCurrentGridState($event)"
(sgOnRowCountChanged)="refreshMetrics($event.detail.eventData, $event.detail.args)">
</angular-slickgrid>
</div>
14 changes: 11 additions & 3 deletions src/app/examples/grid-clientside.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
function randomBetween(min, max) {
return Math.floor(Math.random() * (max - min + 1) + min);
}
const NB_ITEMS = 500;
const NB_ITEMS = 1000;
const URL_SAMPLE_COLLECTION_DATA = 'assets/data/collection_500_numbers.json';

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

setSomeFilters() {
// we can Set Some Filters (or different filters) afterward through the FilterService
this.angularGrid.filterService.updateFilters([
{ columnId: 'duration', searchTerms: [10, 220] },
{ columnId: 'usDateShort', operator: '<', searchTerms: ['4/20/25'] },
]);
}

refreshMetrics(e, args) {
if (args && args.current > 0) {
setTimeout(() => {
Expand Down
6 changes: 3 additions & 3 deletions src/app/examples/grid-graphql.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ <h2>{{title}}</h2>
<button class="btn btn-default btn-xs" data-test="goto-last-page" (click)="goToLastPage()">
<i class="fa fa-caret-right fa-lg"></i>
</button>
<button class="btn btn-default btn-xs" (click)="setSomeFilters()">Set Some Filters</button>
</div>
</div>
<div class="col-sm-7">
Expand All @@ -45,8 +46,7 @@ <h2>{{title}}</h2>
</div>

<angular-slickgrid gridId="grid6" [gridHeight]="200" [gridWidth]="900" [columnDefinitions]="columnDefinitions"
[gridOptions]="gridOptions" [dataset]="dataset" (onAngularGridCreated)="angularGridReady($event)"
(onGridStateChanged)="gridStateChanged($event)"
(onBeforeGridDestroy)="saveCurrentGridState($event)">
[gridOptions]="gridOptions" [dataset]="dataset" (onAngularGridCreated)="angularGridReady($event)"
(onGridStateChanged)="gridStateChanged($event)" (onBeforeGridDestroy)="saveCurrentGridState($event)">
</angular-slickgrid>
</div>
13 changes: 13 additions & 0 deletions src/app/examples/grid-graphql.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,19 @@ export class GridGraphqlComponent implements OnInit, OnDestroy {
console.log('GraphQL current grid state', this.angularGrid.gridStateService.getCurrentGridState());
}

setSomeFilters() {
const presetLowestDay = moment().add(-2, 'days').format('YYYY-MM-DD');
const presetHighestDay = moment().add(20, 'days').format('YYYY-MM-DD');

// we can Set Some Filters (or different filters) afterward through the FilterService
this.angularGrid.filterService.updateFilters([
{ columnId: 'gender', searchTerms: ['male'], operator: OperatorType.equal },
{ columnId: 'name', searchTerms: ['John Doe'], operator: OperatorType.contains },
{ columnId: 'company', searchTerms: ['xyz'], operator: 'IN' },
{ columnId: 'finish', searchTerms: [presetLowestDay, presetHighestDay], operator: OperatorType.rangeInclusive },
]);
}

switchLanguage() {
this.selectedLanguage = (this.selectedLanguage === 'en') ? 'fr' : 'en';
this.translate.use(this.selectedLanguage);
Expand Down
11 changes: 6 additions & 5 deletions src/app/examples/grid-odata.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,16 +24,16 @@ <h2>{{title}}</h2>
<span data-test="radioVersion">
<label class="radio-inline control-label" for="radio2">
<input type="radio" name="inlineRadioOptions" data-test="version2" id="radio2" checked [value]="2"
(change)="setOdataVersion(2)"> 2
(change)="setOdataVersion(2)"> 2
</label>
<label class="radio-inline control-label" for="radio4">
<input type="radio" name="inlineRadioOptions" data-test="version4" id="radio4" [value]="4"
(change)="setOdataVersion(4)"> 4
(change)="setOdataVersion(4)"> 4
</label>
</span>
<label class="checkbox-inline control-label" for="enableCount" style="margin-left: 20px">
<input type="checkbox" id="enableCount" data-test="enable-count" [checked]="isCountEnabled"
(click)="changeCountEnableFlag()">
(click)="changeCountEnableFlag()">
<span style="font-weight: bold">Enable Count</span> (add to OData query)
</label>
</div>
Expand All @@ -46,10 +46,11 @@ <h2>{{title}}</h2>
<button class="btn btn-default btn-xs" data-test="goto-last-page" (click)="goToLastPage()">
<i class="fa fa-caret-right fa-lg"></i>
</button>
<button class="btn btn-default btn-xs" (click)="setSomeFilters()">Set Some Filters</button>
</div>

<angular-slickgrid gridId="grid5" [columnDefinitions]="columnDefinitions" [gridOptions]="gridOptions"
[dataset]="dataset" (onGridStateChanged)="gridStateChanged($event)"
(onAngularGridCreated)="angularGridReady($event)">
[dataset]="dataset" (onGridStateChanged)="gridStateChanged($event)"
(onAngularGridCreated)="angularGridReady($event)">
</angular-slickgrid>
</div>
8 changes: 8 additions & 0 deletions src/app/examples/grid-odata.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,14 @@ export class GridOdataComponent implements OnInit {
this.angularGrid.paginationService.goToLastPage();
}

setSomeFilters() {
// we can Set Some Filters (or different filters) afterward through the FilterService
this.angularGrid.filterService.updateFilters([
// { columnId: 'gender', searchTerms: ['male'], operator: OperatorType.equal },
{ columnId: 'name', searchTerms: ['A'], operator: 'a*' },
]);
}

/** This function is only here to mock a WebAPI call (since we are using a JSON file for the demo)
* in your case the getCustomer() should be a WebAPI function returning a Promise
*/
Expand Down
48 changes: 2 additions & 46 deletions src/app/modules/angular-slickgrid/extensions/gridMenuExtension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import { FilterService } from '../services/filter.service';
import { SortService } from '../services/sort.service';
import { castToPromise } from '../services/utilities';
import { SharedService } from '../services/shared.service';
import { refreshBackendDataset } from '../services/backend-utilities';

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

/** Refresh the dataset through the Backend Service */
refreshBackendDataset(gridOptions?: GridOption) {
let query = '';

// user can pass new set of grid options which will override current ones
if (gridOptions) {
this.sharedService.gridOptions = { ...this.sharedService.gridOptions, ...gridOptions };
}

const backendApi = this.sharedService.gridOptions.backendServiceApi;
if (!backendApi || !backendApi.service || !backendApi.process) {
throw new Error(`BackendServiceApi requires at least a "process" function and a "service" defined`);
}

if (backendApi.service) {
query = backendApi.service.buildQuery();
}

if (query && query !== '') {
// keep start time & end timestamps & return it after process execution
const startTime = new Date();

if (backendApi.preProcess) {
backendApi.preProcess();
}

// the process could be an Observable (like HttpClient) or a Promise
// in any case, we need to have a Promise so that we can await on it (if an Observable, convert it to Promise)
const observableOrPromise = backendApi.process(query);

castToPromise(observableOrPromise).then((processResult: GraphqlResult | any) => {
const endTime = new Date();

// from the result, call our internal post process to update the Dataset and Pagination info
if (processResult && backendApi && backendApi.internalPostProcess) {
backendApi.internalPostProcess(processResult);
}

// send the response process to the postProcess callback
if (backendApi && backendApi.postProcess) {
if (processResult instanceof Object) {
processResult.metrics = {
startTime,
endTime,
executionTime: endTime.valueOf() - startTime.valueOf(),
totalItemCount: this.sharedService.gridOptions && this.sharedService.gridOptions.pagination && this.sharedService.gridOptions.pagination.totalItems
};
// @deprecated
processResult.statistics = processResult.metrics;
}
backendApi.postProcess(processResult);
}
});
}
refreshBackendDataset(backendApi, this.sharedService.gridOptions);
}

showGridMenu(e) {
Expand Down
24 changes: 19 additions & 5 deletions src/app/modules/angular-slickgrid/filters/compoundDateFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ export class CompoundDateFilter implements Filter {
return this._currentDate;
}

/** Getter to know what would be the default operator when none is specified */
get defaultOperator(): OperatorType | OperatorString {
return OperatorType.empty;
}

/** Getter for the Flatpickr Options */
get flatpickrOptions(): FlatpickrOption {
return this._flatpickrOptions || {};
Expand All @@ -69,7 +74,7 @@ export class CompoundDateFilter implements Filter {

/** Getter for the Filter Operator */
get operator(): OperatorType | OperatorString {
return this._operator || this.columnFilter.operator || OperatorType.empty;
return this._operator || this.columnFilter.operator || this.defaultOperator;
}

/**
Expand Down Expand Up @@ -139,17 +144,26 @@ export class CompoundDateFilter implements Filter {
}
}

/**
* Set value(s) on the DOM element
*/
setValues(values: SearchTerm | SearchTerm[]) {
/** Set value(s) in the DOM element, we can optionally pass an operator and/or trigger a change event */
setValues(values: SearchTerm | SearchTerm[], operator?: OperatorType | OperatorString, triggerChange = false) {
if (this.flatInstance && values && Array.isArray(values)) {
this._currentDate = values[0] as Date;
this.flatInstance.setDate(values[0]);
} else if (this.flatInstance && values && values) {
this._currentDate = values as Date;
this.flatInstance.setDate(values);
}

this.operator = operator || this.defaultOperator;
if (operator && this.$selectOperatorElm) {
this.$selectOperatorElm.val(operator);
}

if (triggerChange) {
this._clearFilterTriggered = false;
this._shouldTriggerQuery = true;
this.onTriggerEvent(new Event('change'));
}
}

//
Expand Down
20 changes: 18 additions & 2 deletions src/app/modules/angular-slickgrid/filters/compoundInputFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,11 @@ export class CompoundInputFilter implements Filter {
return this.columnDef && this.columnDef.filter || {};
}

/** Getter to know what would be the default operator when none is specified */
get defaultOperator(): OperatorType | OperatorString {
return OperatorType.empty;
}

/** Getter of input type (text, number, password) */
get inputType() {
return this._inputType;
Expand All @@ -55,7 +60,7 @@ export class CompoundInputFilter implements Filter {

/** Getter of the Operator to use when doing the filter comparing */
get operator(): OperatorType | OperatorString {
return this._operator || OperatorType.empty;
return this._operator || this.defaultOperator;
}

/** Getter of the Operator to use when doing the filter comparing */
Expand Down Expand Up @@ -124,10 +129,21 @@ export class CompoundInputFilter implements Filter {
/**
* Set value(s) on the DOM element
*/
setValues(values: SearchTerm[]) {
setValues(values: SearchTerm[], operator?: OperatorType | OperatorString, triggerChange = false) {
if (values && Array.isArray(values)) {
this.$filterInputElm.val(values[0]);
}

this.operator = operator || this.defaultOperator;
if (operator && this.$selectOperatorElm) {
this.$selectOperatorElm.val(operator);
}

if (triggerChange) {
this._clearFilterTriggered = false;
this._shouldTriggerQuery = true;
this.onTriggerEvent(new Event('change'));
}
}

//
Expand Down
24 changes: 22 additions & 2 deletions src/app/modules/angular-slickgrid/filters/dateRangeFilter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,14 +58,26 @@ export class DateRangeFilter implements Filter {
return this._currentDates;
}

/** Getter to know what would be the default operator when none is specified */
get defaultOperator(): OperatorType | OperatorString {
return this.gridOptions.defaultFilterRangeOperator || OperatorType.rangeExclusive;
}

/** Getter for the Flatpickr Options */
get flatpickrOptions(): FlatpickrOption {
return this._flatpickrOptions || {};
}

/** Getter of the Operator to use when doing the filter comparing */
get operator(): OperatorType | OperatorString {
return this.columnFilter.operator || this.gridOptions.defaultFilterRangeOperator || OperatorType.rangeExclusive;
return this.columnFilter && this.columnFilter.operator || this.defaultOperator;
}

/** Setter for the filter operator */
set operator(operator: OperatorType | OperatorString) {
if (this.columnFilter) {
this.columnFilter.operator = operator;
}
}

/**
Expand Down Expand Up @@ -131,7 +143,7 @@ export class DateRangeFilter implements Filter {
* Set value(s) on the DOM element
* @params searchTerms
*/
setValues(searchTerms: SearchTerm[]) {
setValues(searchTerms: SearchTerm[], operator?: OperatorType | OperatorString, triggerChange = false) {
let pickerValues = [];

// 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
Expand All @@ -145,6 +157,14 @@ export class DateRangeFilter implements Filter {
this._currentDates = pickerValues;
this.flatInstance.setDate(pickerValues);
}

this.operator = operator || this.defaultOperator;

if (triggerChange) {
this._clearFilterTriggered = false;
this._shouldTriggerQuery = true;
this.onTriggerEvent(undefined);
}
}

//
Expand Down

0 comments on commit 8c10e5a

Please sign in to comment.