This is a simple implementation of an ng2 filter pipe, which can currently take 2 optional facets: <string>status
and <string>description
. A "filter pipe" is an angular2 view decorator.
The filter receives a list of objects (values
) which I want to filter by some criteria specific to the type of data object passed to it. The types of criteria are known in advance for each type of object.
Currently, I have implemented only one object type, a "maintenance event", which can be filtered by:
- a status field, which is a fixed enum of strings, and
- a free-text description
The filter is implemented in the view like so:
<div *ngFor="let event of maintenanceEvents | filter:'MAINTENANCE_EVENT':statusFilter:wordFilter">
where statusFilter
and wordFilter
are populated by a form.
The rest parameter (...filters
) was used to allow any future arbitrary number of filters to be passed to the common filter module. So, in future, I could implement a filter like this:
<div *ngFor="let person of people | filter:'PEOPLE':title:permissions:locations:reports">
This is my complete pipe module:
import { Pipe, PipeTransform } from "@angular/core";
@Pipe({ name: 'filter' })
export class FilterPipe implements PipeTransform {
transform(values: any, type: string, ...filters: Object[]): any {
switch (type) {
case 'MAINTENANCE_EVENT':
const ALL = "Show all";
const BLANK = "";
const DESCRIPTION_FILTER = new RegExp(<string>filters[1], 'gi');
if (filters.length !== 2) {
throw new SyntaxError('MAINTENANCE_EVENT requires exactly 2 filter parameters: <string>status and <string>description')
}
if (filters[0] === ALL && filters[1] === BLANK) {
return values;
}
else {
return values.filter(value => {
if (value.hasOwnProperty('status') && value.hasOwnProperty('part') && value.part.hasOwnProperty('description')) {
if (filters[0] === ALL && filters[1] !== BLANK) {
return DESCRIPTION_FILTER.test(value['part']['description']);
}
else if (filters[0] !== ALL && filters[1] === BLANK) {
return value.status === filters[0];
}
else if (filters[0] !== ALL && filters[1] !== BLANK) {
return value.status === filters[0] && DESCRIPTION_FILTER.test(value['part']['description']);
}
}
else {
console.error("Attempting to filter by properties not present in available <MaintenanceEvent>s");
}
});
}
default:
// Return everything
return values;
}
}
}
Particularly, I'm interested in an alternative to the if, else if, else if ... else if N
chain, since this will become wholly unmaintainable for filters with more complex facets (we plan for as many as 9 in future).