This is a migrated thread and some comments may be shown as answers.

How to introduce a nested AND / OR level to filtering

3 Answers 1088 Views
Grid
This is a migrated thread and some comments may be shown as answers.
Murray
Top achievements
Rank 1
Iron
Veteran
Murray asked on 13 May 2020, 05:03 PM

    I've been asked to implement a feature whereby we have logic operators applied on the field level as well as operators applied between fields. Is there any way I can utilize the existing filters functionality to implement this? I would add a further toggle switch to each filter menu to represent this outer logic.

I tried initialising my state filters to the below but this generated errors when trying to open filter menus.

    filter: {
      filters: [ { logic: "or", filters : [] }, { logic: "and", filters : [] } ], 
      logic: "and",
    },

Or would I have to keep a separate record of which filters are to be OR'ed and AND'ed myself?  How could I do this?

 

 

 

3 Answers, 1 is accepted

Sort by
0
Svet
Telerik team
answered on 15 May 2020, 11:02 AM

Hi Murray,

The filter property of the Grid State accepts an object of type CompositeFilterDescriptor. The CompositeFilterDescriptor has a filter property which can further consist of an array of FilterDescriptors or CompositeFilterDescriptors. That allows to use a different logic operator for a specific filter operation per field and use a separate filter logic operator for all filter fields. Please check the following example demonstrating how the Grid data can be filtered to contain all records which "ProductName" contains "Cha" or all records which "UnitPrice" is between 12 and 20:

https://stackblitz.com/edit/angular-dqzhkx?file=app/app.component.ts

The essential part is the construction of this.customFilter:

export class AppComponent {
  public gridData: any[] = products;
  public customFilterDescriptor: FilterDescriptor = {
    field: "ProductName",
    operator: "contains",
    value: "Cha"
  };
  public customCompositeFilterDescriptor: CompositeFilterDescriptor = {
    logic: "and",
    filters: [
      { field: "UnitPrice", operator: "gte", value: 12 },
      { field: "UnitPrice", operator: "lte", value: 20 }
    ]
  };
  public customFilter: CompositeFilterDescriptor = {
    logic: "or",
    filters: [this.customFilterDescriptor, this.customCompositeFilterDescriptor]
  };

  ngOnInit() {
    this.gridData = process(products, { filter: this.customFilter }).data;
  }

I hope the provided information and example helps. Please let us know in case nay additional details are required for this case. Thank you.

Regards,
Svetlin
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
0
Murray
Top achievements
Rank 1
Iron
Veteran
answered on 18 May 2020, 10:58 AM

The problem is that I need to add a custom OR switch to each column filter like so:

If I initialise my grid filters to the following:

 

filter: {
      filters: [ { logic: "or", filters : [] }, { logic: "and", filters : [] } ], 
      logic: "and",
    },

and I have column filter defintiions like so

 <ng-template
      kendoGridFilterMenuTemplate
      *ngSwitchCase="'string'"
      let-filter
      let-column="column"
      let-filterService="filterService">
      <kendo-grid-string-filter-menu
        [column]="column"
        [extra]="true"
        [filter]="filter"
        [filterService]="filterService">
        <kendo-filter-contains-operator>
        </kendo-filter-contains-operator>
        <kendo-filter-eq-operator>
        </kendo-filter-eq-operator>
        <kendo-filter-neq-operator>
        </kendo-filter-neq-operator>
      </kendo-grid-string-filter-menu>
      <logic-selector
        [currentFilter]="filter"
        [value]="column.value">
      </logic-selector>
    </ng-template>

 

I want my <logic-selector>  AND/OR switch to put the filter in the appropriate "and" or "or" array in the top level filter. However the  filter which gets injected to my logic-selector is the current filter for that column, so it has no access to the outer "or" / "and" filters... Is there any way to achieve this?

0
Svet
Telerik team
answered on 20 May 2020, 09:41 AM

Hi Murray,

Thank you for the provided sample markup.

It seems that you are using a custom menu filter due to the demonstrated kendoGridFilterMenuTemplate. Such custom filter menu is demonstrated in the following article from out documentation:

https://www.telerik.com/kendo-angular-ui/components/grid/filtering/reusable-filter/#toc-multi-checkbox-menu-filtering

the filter per field can be set by the filter method of the filterService as demonstrated in multicheck-filter.component.ts file:

  public onSelectionChange(item, li) {
    if (this.value.some(x => x === item)) {
      this.value = this.value.filter(x => x !== item);
    } else {
      this.value.push(item);
    }

    this.filterService.filter({
        filters: this.value.map(value => ({
            field: this.field,
            operator: 'eq',
            value
        })),
        logic: 'or'
    });

    this.onFocus(li);
  }

and the global filter can be further altered within the (filterChange) or (dataStateChange) event of the Grid. Please check the app.component.ts file:

        <kendo-grid
            [data]="gridData"
            [filter]="filter"
            filterable="menu"
            (filterChange)="filterChange($event)"
            [height]="400"
        >
...

    public filterChange(filter: CompositeFilterDescriptor): void {
        this.filter = filter;
        this.gridData = filterBy(sampleProducts, filter);
    }

However whenever custom filters are used it is considered a developer effort to pass the required custom filter via the filterSerice.filter() method or to manually modify the current filter by handling the (filterChange) or (dataStateChange) events of the Grid.

I hope the provided information helps you to move forward with this case.

Regards,
Svetlin
Progress Telerik

Progress is here for your business, like always. Read more about the measures we are taking to ensure business continuity and help fight the COVID-19 pandemic.
Our thoughts here at Progress are with those affected by the outbreak.
Tags
Grid
Asked by
Murray
Top achievements
Rank 1
Iron
Veteran
Answers by
Svet
Telerik team
Murray
Top achievements
Rank 1
Iron
Veteran
Share this question
or