Column Filters

This section describes how to enable filtering for a column and what events are involved.

Live example

Column Filters live example.

Defining a column as filterable

If you want to filter the DikeGrid rows by a column, you must provide an input property named filterable for that column definition.

Consider the following column definitions:

<dike-grid id="grid-col-filters" height="600px" #grid="dkgGrid"
    (gridColumnDefInstance)="onColumnDefInstance($event)">
    
    <dike-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350"
        order="1"
        sortable>
    </dike-grid-column>

    <dike-grid-column
        fieldName="completeNameGroup"
        headerText="Complete Name"
        order="2">

        <dike-grid-column
            fieldName="firstName"
            headerText="Name"
            dataType="Text"
            width="150"
            sortable
            filterable>
        </dike-grid-column>

        <dike-grid-column
            fieldName="lastName"
            headerText="Surname"
            dataType="Text"
            width="150"
            sortable>
        </dike-grid-column>
    </dike-grid-column>

    <dike-grid-column
        fieldName="gender"
        headerText="Gender"
        dataType="Binary"
        width="110"
        order="3"
        sortable>
    </dike-grid-column>
</dike-grid>

As you can see, we defined the columns Name, Age, and Hire Date as filterable.

If you open the Column Context Menu for a filterable column, you will see the filter option available.

You can not define a column group as filterable.

Initial filter

You can set an initial filter when defining a column.

See the following code:

<dike-grid id="grid-col-filters" height="600px" #grid="dkgGrid">
    <dike-grid-column
        fieldName="completeNameGroup"
        headerText="Complete Name"
        order="2">

        <dike-grid-column
            fieldName="firstName"
            headerText="Name"
            dataType="Text"
            width="150"
            sortable
            filterable
            [filter]="[{ condition: 'startsWith', logicalOperator: 'and', value: 'w' }]">
        </dike-grid-column>

        <dike-grid-column
            fieldName="lastName"
            headerText="Surname"
            dataType="Text"
            width="150"
            sortable>
        </dike-grid-column>
    </dike-grid-column>
</dike-grid>

We have set an initial filter for the Name column in the HTML. For the Age column, we defined the initial filter in code.

Open the Column Context Menu for the Name or the Age column. You will see the filter we have set at creation time.

The type of the object for setting an initial filter depends on the type of the column. For example, the Age column is a Numeric column. Thus, its filter property is of type DikeNumericFilter[].

When defining an initial filter in the HTML template, the filter property is of type DikeFilter[].

See the DikeFilter hierarchy definition.

Modifying filters

You can add or remove filter conditions for any column defined as filterable through the Column Context Menu.

Let us add a condition for the Hire Date column:

You can add any number of conditions joined by logical operators (OR/AND).

Filtering execution

Debounce time

Text and Numeric columns have a debounce time when the user is typing a value to filter the DikeGrid rows. By default, the debounce time is 400 milliseconds.

As you can see, once the time has elapsed, the column sends the filter for its execution.

You can change the time you wait for filter execution by providing the Injection Tokens TEXT_FILTER_DEBOUNCE_TIME and NUMERIC_FILTER_DEBOUNCE_TIME.

Let us change the debounce time for Numeric types.

filtering.module.ts
@NgModule({
  providers: [
    { provide: NUMERIC_FILTER_DEBOUNCE_TIME, useValue: 300 }
  ]
})
export class FilteringModule { }

Filtering on-demand

If you want to control when to send the filter conditions, you can set a flag at grid scope by providing an input property named onDemandFilter.

column-filters.component.html
<dike-grid id="grid-col-filters" height="600px" #grid="dkgGrid"
    [onDemandFilter]="gridProperties.onDemandFilter">
</dike-grid>

Since we take the flag value from the gridProperties object, please open the Floating Configuration Panel and mark the checkbox on-demand Filter under the Filtering section.

Open the Column Context Menu for a filterable column. Next, you will see the Filter button. Click on this button when you have finished defining the filter conditions for the column.

Filtering using the API

You can achieve all the previous tasks by using the corresponding API.

Before using the API, we have to retrieve the DikeGrid instance from the component's view.

<dike-grid id="grid-col-filters" height="600px" #grid="dkgGrid">
</dike-grid>

DikeGrid Column API

Using the column API, you can change, at runtime, a column definition to be filterable or change its filter conditions.

The following methods belong to the column API regarding filtering:

MethodDescription

setColumnFilterablility()

Use this method to change a column to be filterable. You can provide an initial filter to be applied.

changeColumnFilter()

This method sets the given filter definition for the given column.

For further details, see the DikeGridColumnDef definition.

DikeGrid Filter API

The following methods comprise the filter API:

MethodDescription

clearFilter()

This method will remove all the filter conditions from every filterable.

isFilterApplied()

It returns a boolean value indicating if the DikeGrid instance has one filter condition, at least.

getFilteredRows()

It returns all the rows that meet all the filter conditions criteria.

For further details, see the DikeGridFilter definition.

To see the API in action, let us define the following UI:

<div class="mt-2 flex flex-row flex-wrap items-center justify-around">
    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onColumnAsFilterable()">Surname - filterable
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onInitialFilter()">Email - Initial filter
        </button>
    </div>

    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onChangeColumnFilter()">Age - Change column filter
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onGetFilterables()">Filterables
        </button>
    </div>

    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onGetFilteredRows()">Filtered rows
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onClearFilter()">Clear filter
        </button>
    </div>
</div>

<dike-grid id="grid-col-filters" height="600px" #grid="dkgGrid">
</dike-grid>

The previous definition generates the following output:

In the following list, we describe every button action:

  1. Surname - filterable. Click on this button to make the Surname column filterable or not filterable. It toggles the current filterable value.

  2. Email - Initial filter. Same as before, it toggles the current filterable value. When the column becomes filterable, the given filter is applied. Otherwise, the DikeGrid instance will ignore the given filter.

  3. Age - Change column filter. Since the Age column is filterable, we change its filter, merging the current condition with the new one. If you click more than once, the action will append the new filter condition to the existing ones.

  4. Filterables. Clicking on this button will print out, to the dev console, the current filterables.

  5. Filtered rows. Clicking on this button will print out, to the dev console, all the rows that meet the filter conditions criteria.

  6. Clear filter. Clicking on this button will remove all the filter conditions.

When defining a column as filterable, the DikeGrid registers that column in an internal Map structure named filterables. The items of this Map are of type DikeFilterable.

Filter Events

When defining a column as filterable or adding/removing a filter condition, the DikeGrid instance emits the related events.

The filter events are:

EventDescription

registerFilterableChange

It emits when you define a column as filterable. Then, the DikeGrid instance will add the column to the internal Map named filterables.

deregisterFilterableChange

It emits when you make a column not filterable when it was filterable. Then, the DikeGrid instance will remove the column to the internal Map named filterables.

filterChange

It emits when the user has defined/changed a filter condition.

clearFilterChange

It emits after the DikeGrid instance has removed all the filter conditions.

Let us listen to these events:

<dike-grid id="grid-col-filters" height="600px" #grid="dkgGrid"
    (registerFilterableChange)="onRegisterChange($event)"
    (deregisterFilterableChange)="onDeregisterChange($event)"
    (filterChange)="onFilterChange($event)"
    (clearFilterChange)="onClearFilterChange()">
</dike-grid>

Please, open your dev console to see the output of these events.

You can also listen to these events from the DikeGridFilter instance.

Row Grouping and Filtering

When grouping the DikeGrid rows by a column and filtering those rows, you will see the filter icon on the right side of the group name showing how many data rows for that group have met the filter criteria.

We have allowed Row-Grouping, and we have defined the Age column as groupable.

<dike-grid id="grid-col-filters" height="600px" #grid="dkgGrid"
    allowRowGrouping
    [allowColumnDragging]="gridProperties.allowColumnDragging">
</dike-grid>

If you group the DikeGrid rows by a column with filters, the DikeGrid will ignore those filters.

As you can see in the previous output, the DikeGrid ignores the filter when grouping the DikeGrid rows by the Age column despite defining a filter for this column. As a result, the DikeGrid shows all the values for the Age column as groups.

Summary

It is enough to define a column as filterable to give the user the ability to filter the DikeGrid rows. The user can add any number of filter conditions. By default, Text and Numeric filter types have a debounce time, but you can change this value or send filters on-demand.

You can use the column API and the filter API to perform filtering tasks. All the filter actions emit their corresponding event.

Complete code for this section.

<div class="mt-2 flex flex-row flex-wrap items-center justify-around">
    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onColumnAsFilterable()">Surname - filterable
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onInitialFilter()">Email - Initial filter
        </button>
    </div>

    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onChangeColumnFilter()">Age - Change column filter
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onGetFilterables()">Filterables
        </button>
    </div>

    <div class="flex-none w-56 flex flex-col m-2 items-center">
        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onGetFilteredRows()">Filtered rows
        </button>

        <button mat-raised-button
            class="flex-none w-56 my-2"
            color="primary"
            (click)="onClearFilter()">Clear filter
        </button>
    </div>
</div>
<dike-grid id="grid-col-filters" height="600px" #grid="dkgGrid"
    [displayRowId]="gridProperties.displayRowId"
    [gridElevation]="gridProperties.matElevation"
    [gridElevationValue]="gridProperties.elevationValue"
    [striped]="gridProperties.stripeRows"
    [verticalRowLines]="gridProperties.verticalRowLines"

    allowRowGrouping
    [allowColumnDragging]="gridProperties.allowColumnDragging"
    [allowSorting]="gridProperties.allowSorting"
    [onDemandFilter]="gridProperties.onDemandFilter"

    (registerFilterableChange)="onRegisterChange($event)"
    (deregisterFilterableChange)="onDeregisterChange($event)"
    (filterChange)="onFilterChange($event)"
    (clearFilterChange)="onClearFilterChange()"

    (gridColumnDefInstance)="onColumnDefInstance($event)"
    [datasource]="dkgDataSource">

    <dike-grid-column
        fieldName="employeeId"
        headerText="Employee Id"
        dataType="Text"
        width="350"
        order="1"
        sortable>
    </dike-grid-column>
    
    <dike-grid-column
        fieldName="completeNameGroup"
        headerText="Complete Name"
        order="2">

        <dike-grid-column
            fieldName="firstName"
            headerText="Name"
            dataType="Text"
            width="150"
            sortable
            filterable
            [filter]="[{ condition: 'startsWith', logicalOperator: 'and', value: 'w' }]">
        </dike-grid-column>

        <dike-grid-column
            fieldName="lastName"
            headerText="Surname"
            dataType="Text"
            width="150"
            sortable>
        </dike-grid-column>
    </dike-grid-column>
    
    <dike-grid-column
        fieldName="gender"
        headerText="Gender"
        dataType="Binary"
        width="110"
        order="3"
        sortable>
    </dike-grid-column>
    
</dike-grid>    

Last updated