Angular2: filtering ngFor using pipes
Angular2 / Bootstrap4 table¶
I'm still working on a Stripe administration console for OctoPerf, a SaaS performance testing tool. Stripe lets us manage our customers and their subscriptions.
I have a table that lists all of our customers (Customers.html
):
<table class="table table-striped">
<thead class="thead-default">
<tr>
<th>#</th>
<th>Id</th>
<th>Email</th>
</tr>
</thead>
<tbody>
<tr *ngFor="#customer of customers; #i = index">
<th scope="row">{{i}}</th>
<td>{{customer.id}}</td>
<td>{{customer.email}}</td>
</tr>
</tbody>
</table>
It's an Angular2 application build using this excellent starter with BootStrap 4.
Filtering the content using a Pipe¶
Our goal is to filter the customers by their email. The first step is to create a PipeTransform implementation:
import {Injectable, Pipe, PipeTransform} from 'angular2/core';
import {Customer} from '../services/Customer';
@Pipe({
name: 'customerEmailFilter'
})
@Injectable()
export class CustomerEmailFilter implements PipeTransform {
transform(customers: Customer[], args: any[]): any {
return customers.filter(customer => customer.email.toLowerCase().indexOf(args[0].toLowerCase()) !== -1);
}
}
It's pretty much like the AngularJS filters. The transform method takes a customers array and some args as parameters and filters the array depending on the arg value.
Note:
We don't have to set a type like
customers: Customer[]
to the transformed list. We could also create a more generic filter using an object array:items: any[]
.
Using the Pipe in our table component¶
To use the email filter in our Customers table component we must declare it in the annotation:
import {Component} from 'angular2/core';
import {StripeClient} from '../services/StripeClient';
import {Customer} from '../services/Customer';
import {CustomerEmailFilter} from './CustomerEmailFilter';
@Component({
selector: 'customers',
pipes: [CustomerEmailFilter],
providers: [],
directives: [],
styles: [require('./Customers.css')],
template: require('./Customers.html'),
})
export class Customers {
private customers: Customer[];
private email: string = '';
constructor(private client: StripeClient) {
this.customers = [];
}
ngOnInit() {
this.client.getCustomers((customers: Customer[]) => {
this.customers = customers;
});
}
}
The pipes: [CustomerEmailFilter],
line allows us to use customerEmailFilter
in the Customers.html
file.
We also declare a field email
that holds the value for the filter argument.
The resulting html file has an input text in the table header. It allows the user to set the filter value: [(ngModel)]="email"
.
<table class="table table-striped">
<thead class="thead-default">
<tr>
<th>#</th>
<th>Id</th>
<th><input type="text" id="inputEmail" class="form-control" placeholder="Email" [(ngModel)]="email"></th>
</tr>
</thead>
<tbody>
<tr *ngFor="#customer of customers | customerEmailFilter:email; #i = index">
<th scope="row">{{i}}</th>
<td>{{customer.id}}</td>
<td>{{customer.email}}</td>
</tr>
</tbody>
</table>
And the ngFor is now filtered: *ngFor="#customer of customers | customerEmailFilter:email
.
Notes:
customerEmailFilter
is the name of the CustomerEmailFilter declared in the @Pipe annotation.
The resulting table: