Apply custom In Between Filter for PrimeNG: Datatable

Kishor Prakash picture Kishor Prakash · Mar 12, 2018 · Viewed 11.8k times · Source

Consider a scenario where I am displaying a START and END YEARs in a p-dataTable column.

Here is the column code snippet:

<p-column field="startYear" header="Active Period" filterPlaceholder="Search" [filter]="true">
  <ng-template let-col let-manual="rowData" pTemplate="body">
    {{record.startYear}} - {{record.endYear}}
  </ng-template>
</p-column>

Which displays as:

|--------------|
| ActivePeriod |
|--------------|
|2015 - 2017   |
|--------------|
|2012 - 2016   |
|--------------|
|2023 - 2025   |
|--------------|
|2024 - 2030   |
|--------------|
|2011 - 2013   |
|--------------|

I want to apply a custom filter so that when user types in an YEAR the table should only show the records which falls in that Active period.

Which means I have to write a logic where I have check if the user searched year is in between each active period.

How can I achieve this?

Answer

Andriy picture Andriy · Mar 12, 2018

First, you can add hidden assistant field years which will contain an array with years within given range, so for range 2012 - 2015, we will get an array:

[
  2012,
  2013,
  2014,
  2015
]

You can do it using map function, something like:

const yearsRange = row.endYear - row.startYear + 1;
YOUR_DATA_ARRAY.map(row => ({
  ...row,
  years: [...Array(yearsRange).keys()].map(y => y + row.startYear)
}))

Out of the box PRIME NG does not have between filter. Filters available currently are:

  • startsWith
  • contains
  • endsWith
  • equals
  • notEquals
  • in
  • lt
  • gt

You can extend it writing your own filter:

// import Table class
import { Table } from 'primeng/components/table/table';

.....

// get reference to your table
@ViewChild('dt') tableRef: Table;

.....

// extend filters
this.tableRef.filterConstraints.between = (value, filter: any): boolean => {
  if (filter === undefined || filter === null || filter === '') {
    return true;
  }

  if (value === undefined || value === null || !value.length) {
    return false;
  }

  return value.some(val => +val === +filter);
};

now you can use it in your HTML:

<p-table #dt [value]="cars">

  .....

  <input size="4"
         (input)="dt.filter($event.target.value, 'years', 'between')">

  .....

STACKBLITZ: https://stackblitz.com/edit/angular-sfoh3j?file=app%2Fapp.component.ts

UPDATE

I noticed you use old (and deprecated) DataTable, the solution should be very similar, filters are almost the same missing lt and gt. Just change names in imports and type names in my example. HTML syntax is also different. Let me know if you need help with old DataTable