Basicly all info is provided in the title.
It seems to me that I am bound to the filterMatchModes that are available ( contains, in, equals, endsWith, startsWith). In my usecase my column field is an array, and no single value.
My specified column looks like this:
<p-column field="types" [filter]="true" header="{{'AIRPORTS.TYPES' | translate}}">
<template let-airport="rowData" pTemplate="body">
<span *ngFor="let type of airport.types; let isLast = last">
{{('AIRPORTS.' + type) | translate}}{{isLast ? '' : ', '}}
</span>
</template>
<template pTemplate="filter" let-col>
<p-dropdown [options]="choices"
[style]="{'width':'100%'}"
(onChange)="airportsDataTable.filter($event.value,col.field,col.filterMatchMode)"
styleClass="ui-column-filter">
</p-dropdown>
</template>
</p-column>
I had a similar problem where I had to filter array column-data with multiple selectable filter-values (from a p-multiSelect
, so the filter was an array too).
I figured out a way to extend the available filterMatchModes with some help from the original source-code. Unfortunately I can't vouch for it being good practice, but hey, in the version I'm using (PrimeNG 4.1.2) it works.
You may have to adapt and tune your filter-function to your needs, but here is what my solution would look like in your case (with a p-dropdown
):
#dt
)@ViewChild
-decoratorngOnInit()
)component.ts
@Component({...})
export class DatatableComponent implements OnInit {
...
@ViewChild('dt') dt: DataTable;
...
ngOnInit() {
this.dt.filterConstraints['inCollection'] = function inCollection(value: any[], filter: any): boolean {
// value = array of data from the current row
// filter = value from the filter that will be searched in the value-array
if (filter === undefined || filter === null) {
return true;
}
if (value === undefined || value === null || value.length === 0) {
return false;
}
for (let i = 0; i < value.length; i++) {
if (value[i].toLowerCase() === filter.toLowerCase()) {
return true;
}
}
return false;
}
}
}
In your view you can now use the new filter-function by setting the filterMatchMode of the column to what you named it before:
component.html
<p-dataTable #dt ...>
...
<p-column field="types" filterMatchMode="inCollection" header="{{'AIRPORTS.TYPES' | translate}}">
<template let-airport="rowData" pTemplate="body">
<span *ngFor="let type of airport.types; let isLast = last">
{{('AIRPORTS.' + type) | translate}}{{isLast ? '' : ', '}}
</span>
</template>
<template pTemplate="filter" let-col>
<p-dropdown [options]="choices"
[style]="{'width':'100%'}"
(onChange)="dt.filter($event.value,col.field,col.filterMatchMode)"
styleClass="ui-column-filter">
</p-dropdown>
</template>
</p-column>
...
</p-dataTable>
All I did in the view was set the filterMatchMode
, otherwise I copied your code. (I also renamed the template-reference to #dt
to make it shorter and more readable)
Hint: you don't need [filter]=true
in this column, since the standard filter won't show when your column has a custom filter-template.
As I mentioned, with a custom filter function like this you can for example implement filtering array-data with a p-multiSelect
filter (nested loop in filter-function), search for substrings in array or whatever else you can think of.
As a simple workaround, you can directily change the FilterUtils:
import { FilterUtils } from 'primeng/utils';
FilterUtils['filterTest'] = (value, filter) => value <= filter && value >= filter;
this.dt.filter(search, 'field', 'filterTest');
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With