Pipes are a useful tool in Angular. I've briefly talked about using a couple of the built in pipes in my Angular Concepts Post but it's also very easy to make your own custom pipes to transform the data in whatever way you may need. Just as components, modules, etc., Angular has the tools so that you can create a pipe quickly and easily using the Angular CLI.
In this short tutorial, we'll just create a custom pipe that will transform some text that we receive from an API into something a little bit more friendly. We're outputting our data to a table.
<table mat-table matSort [dataSource]="dataSource" class="mat-elevation-z8">
<ng-container [matColumnDef]="column" *ngFor="let column of displayedColumns">
<th mat-header-cell mat-sort-header={{column}} *matHeaderCellDef> {{column}} </th>
<td mat-cell *matCellDef="let element"> {{element[column]}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplay"></tr>
<tr mat-row *matRowDef="let row; columns: columnsToDisplay;"></tr>
</table>
And below is the corresponding component class
import { Component, OnInit} from '@angular/core';
export interface PeriodicElement {
name: string;
position: number;
weight: number;
symbol: string;
}
const ELEMENT_DATA: PeriodicElement[] = [
{position: 1, name: 'Hydrogen', weight: 1.0079, symbol: 'H'},
{position: 2, name: 'Helium', weight: 4.0026, symbol: 'He'},
{position: 3, name: 'Lithium', weight: 6.941, symbol: 'Li'},
{position: 4, name: 'Beryllium', weight: 9.0122, symbol: 'Be'},
{position: 5, name: 'Boron', weight: 10.811, symbol: 'B'},
{position: 6, name: 'Carbon', weight: 12.0107, symbol: 'C'},
{position: 7, name: 'Nitrogen', weight: 14.0067, symbol: 'N'},
{position: 8, name: 'Oxygen', weight: 15.9994, symbol: 'O'},
{position: 9, name: 'Fluorine', weight: 18.9984, symbol: 'F'},
{position: 10, name: 'Neon', weight: 20.1797, symbol: 'Ne'},
];
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit{
constructor(){}
displayedColumns: string[] = ['name', 'weight', 'symbol', 'position'];
columnsToDisplay: string[] = this.displayedColumns.slice();
dataSource = ELEMENT_DATA
ngOnInit() {}
}
Your output should look like this:
ng g p pipes/prettyLookup
.The pretty-lookup.pipe.ts
file will look like below with a standard boilerplate. transform
is the function that will be performed whenever the pipe is used. value
will be the parameter that the transform is done to. ...args
will be any parameters that you wish to specify after the colon when defining the pipe.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'prettyLookup'
})
export class PrettyLookupPipe implements PipeTransform {
transform(value: unknown, ...args: unknown[]): unknown {
return null;
}
}
<th mat-header-cell mat-sort-header={{column}} *matHeaderCellDef> {{column | prettyLookup}} </th>
<td mat-cell *matCellDef="let element"> {{element[column] | prettyLookup}} </td>
Now every element of the table will have their text transformed by the prettyLookup
pipe. Take a look.
Saying hello in your table is very polite but is not very useful for any application that we'd like to build. Let's take this a step further, let's say that we want our table headings to be in spanish. Let's do that by creating a simple lookup object.
We'll create a spanish lookup object so that we can use the english names as keys and the spanish names as values. We'll also modify the transform function to use this spanishLookup object to return the corresponding spanish name. If the value is not found is our object, we'll simply return the original value.
export class PrettyLookupPipe implements PipeTransform {
spanishLookup = {
'name': 'nombre',
'weight': 'peso',
'symbol': 'símbolo',
'position': 'posición'
}
transform(value: string, type: string): unknown {
let prettyLookup = this.spanishLookup[value]
if(!prettyLookup){
return value
}
return prettyLookup
}
}
Now, take a look at the table being rendered
Notice that we also added a type
parameter to our function. This is so that we can even take the pipe one step further and choose between a spanish and french translation.
export class PrettyLookupPipe implements PipeTransform {
spanishLookup:object = {
'name': 'nombre',
'weight': 'peso',
'symbol': 'símbolo',
'position': 'posición'
}
frenchLookup:object = {
'name': 'Nom',
'weight': 'poids',
'symbol': 'symbole',
'position': 'position'
}
transform(value: string, type: string): unknown {
let prettyLookup:string = ''
if(type=="spanish"){
prettyLookup = this.spanishLookup[value]
}else if(type=="french"){
prettyLookup = this.frenchLookup[value]
}
if(!prettyLookup){
return value
}
return prettyLookup
}
}
'french'
parameter.<th mat-header-cell mat-sort-header={{column}} *matHeaderCellDef> {{column | prettyLookup:'french'}} </th>
Notice that the parameter must be quoted because we are passing a string.
Now, take a look at the rendered table. We can also pass the 'spanish'
string as a parameter in the html above to receive the spanish translations. We can even pass no parameter to have the table headings remain in English.
Pipes are a powerful tool in Angular. The data in the example above was hardcoded to the component class but if we're receiving the data from an API, we're unable to transform the data at the source. This could be where Angular Pipes jump into action.