pipes used to transform output to template
in sample's app.component an array of servers is instantiated
NOTE : months are zer-based (go figure)
...
export class AppComponent {
servers = [
{
instanceType: 'medium',
name: 'Production Server',
status: 'stable',
started: new Date(2017, 9, 13)
},
...
];
getStatusClasses(server: {instanceType: string, name: string, status: string, started: Date}) {
return {
'list-group-item-success': server.status === 'stable',
'list-group-item-warning': server.status === 'offline',
'list-group-item-danger': server.status === 'critical'
};
}
}
in app.component built-in pipes are used to put the server name in uppercase and
the date into a short format
<ul class="list-group">
<li class="list-group-item" *ngFor="let server of servers" [ngClass]="getStatusClasses(server)">
<span class="badge">
{{ server.status }}
</span>
<strong>{{ server.name }}</strong> | {{ server.instanceType | uppercase}} | {{ server.started | date}}
</li>
</ul>
Top
Index
generally parsing is done left to right do the order of pipes can be important
this order will cause an error because the started property is a Date type while
uppercase expects a string
{{ server.started | uppercase | date: 'fullDate' }}
Top
Index
create file named shorten.pipe.ts
set up class implementing PipeTransform interface
add Pipe decorator to class and set the pipe's name property
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'shorten'
})
export class ShortenPipe implements PipeTransform {
transform(value: any) {
if (value.length > 10) {
// return the first 10 chars
return value.substr(0, 10) + ' ...';
}
return value;
}
}
in app.module import ShortenPipe and add type to declarations
...
import { ShortenPipe } from './shorten.pipe';
@NgModule({
declarations: [
AppComponent,
ShortenPipe
],
...
})
export class AppModule { }
in app.component markup use the pipe
<ul class="list-group">
<li class="list-group-item" *ngFor="let server of servers" [ngClass]="getStatusClasses(server)">
<span class="badge">
{{ server.status }}
</span>
{{ server.name | shorten }} | {{ server.instanceType | uppercase}} | {{ server.started | date: 'fullDate' | uppercase }}
</li>
</ul>
only the first ten characters of the server name will be displayed
if server name is less than ten characters no action will be taken
Top
Index
parameterizing a custom pipe
let pipe user determine how many characters to show
...
export class ShortenPipe implements PipeTransform {
transform(value: any, limit: number) {
if (value.length > limit) {
// return the first 10 chars
return value.substr(0, limit) + ' ...';
}
return value;
}
}
to add argument to pipe
<li class="list-group-item" *ngFor="let server of servers" [ngClass]="getStatusClasses(server)">
<span class="badge">
{{ server.status }}
</span>
{{ server.name | shorten: 15}}; | {{ server.instanceType | uppercase}} | {{ server.started | date: 'fullDate' | uppercase }}
</li>
if pipe's argument is omitted the pipe does nothing
Top
Index
Example : creating a filter pipe
to create a pipe using CLI
ng g p <name of pipe>
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'filter'
})
export class FilterPipe implements PipeTransform {
transform(value: any, filterString: string, propName: string): any {
if (value.length === 0 || filterString === '') {
return value;
}
const resultArray = [];
for (const item of value) {
if (item[propName] === filterString) {
resultArray.push(item);
}
}
return resultArray;
}
}
in the component markup the user can enter a status in the textbox
that value is used as an argument to the pipe's transform method
<input type="text" [(ngModel)]="filteredStatus" >
<hr>
<ul class="list-group">
<li class="list-group-item" *ngFor="let server of servers | filter: filteredStatus: 'status'" [ngClass]="getStatusClasses(server)">
<span class="badge">
{{ server.status }}
</span>
{{ server.name | shorten: 15}} | {{ server.instanceType | uppercase}} | {{ server.started | date: 'fullDate' | uppercase }}
</li>
</ul>
Top
Index
by default Angular does not apply pipes as data changes
when the servers array is being filtered a newly added server will not appear in
the list
to change behavior add pure property to the pipe's decorator and set it to false
doing so makes pipe 'recalculate' when any data on the page changes
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'filter',
pure: false
})
export class FilterPipe implements PipeTransform {
...
}
Top
Index
understanding the "async" pipe
in app.component add a property which is a Promise
...
export class AppComponent {
appStatus = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('stable');
}, 2000)
})
...
}
in the markup use string interpolation to display the new property
<h4>App Status : {{ appStatus | async }}</h4>
without the async pipe the property will be displayed as
[object Promise]
with the async pipe the property will be empty until the timeout expires and sets
the property
the async pipe can also be used with Observables
Top
Index