
Software engineer / Angular / C#
Search for a command to run...

Software engineer / Angular / C#
No comments yet. Be the first to comment.
Who's the winner?

Don't call us, we'll call you

For me, January is the most dreaded month of the year. Everything is dark, cold, motivation is low and you have all the existential crisis for a couple of weeks. That's me in January. Not a great presence to be around. This year I wanted to sail agai...

Before is too late

A simple guide

A pipe is a function that transforms an input value into an output value before rendering it in the template.
The class requires to implement the PipeTransform interface.
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'errorMessage'
})
export class ErrorPipe implements PipeTransform {
transform(value: any, args?: any): any {
return 'Error: ' + value;
}
}
You can use it in the code like this
<div *ngIf="error">
<p>{{ error | errorMessage }}</p>
</div>
The problem with using a function in the template is that it will be triggered during the change detection process.
Let’s have this example:
@Component({
selector: 'app-error-message',
template: `
<div *ngIf="error">
<p>{{getErrorMessage()}}</p>
</div>
`,
})
export class MyLibComponent {
@Input() error: string = ''
getErrorMessage() {
return `🛑 Error: ${this.error} 🛑`;
}
}
Because of not knowing what the result of getErrorMessage() will be, Angular Change Detection algorithm will re-run that function each time the change detection cycle will be triggered.
Imagine clicking somewhere in the app and having to re-render this message.
A pipe that solves this problem is called a PURE PIPE
Pure pipes get triggered only when a primitive value or reference is changed
By default, the pipe comes as pure.
More efficient than impure pipes due to change detection.
The result is memoized and every time you get to call the pipe with the parameter you will get the same result.
import { Pipe, PipeTransform } from '@angular/core';
/// In this example, the pipe will be triggered only
/// when the reference of value changes
///
/// If for example I would change only value.error,
/// the pipe will not be triggered
@Pipe({
name: 'errorMessage',
pure: true /// IS SET BY DEFAULT
standalone: true
})
export class ErrorPipe implements PipeTransform {
transform(value: Raport, args?: any): any {
return 'Error: ' + value.error;
}
}
export interface Raport {
id: string;
name: string;
error: string;
}
Impure pipes get triggered even if the nested values are changed.
Change Detection will be triggered even if the value is the same
/// In this example, the pipe will be triggered
/// when value.error changes
@Pipe({
name: 'errorMessage',
pure: false
})
A visual representation always comes in handy:

To use pipes in the TS files, you will have to inject the pipe into the component constructor.
@Component({
selector: 'app-error-message',
template: `
<div *ngIf="error">
<p>{{displayMessage}}</p>
</div>
`,
import: [ErrorPipe]
})
export class MyLibComponent implements OnInit {
@Input() error: string = '';
displayMessage: string = '';
constructor(private errorPipe: ErrorPipe) { }
ngOnInit() {
this.displayMessage = this.getErrorMessage();
}
getErrorMessage() {
return this.errorPipe.transform(this.error);
}
}
If you want to improve DX, you can extract the logic of the pipe in a function so every time you will want to use the pipe in the TS file you will not have to inject the pipe, declare it in the constructor and call the transform method.
const errorMessage = (message: string) => `Error: ${message}`
import { Pipe, PipeTransform } from '@angular/core';
@Pipe({
name: 'errorMessage',
standalone: true
})
export class ErrorPipe implements PipeTransform {
transform(value: string, args?: any): string {
return errorMessage(value);
}
}
import { errorMessage } from './errorMessage';
import { OnInit } from '@angular/core';
@Component({
selector: 'app-error-message',
template: `
<div *ngIf="error">
<p>{{displayMessage}}</p>
</div>
`,
})
export class MyLibComponent implements OnInit {
@Input() error: string = '';
displayMessage: string = '';
constructor() { }
ngOnInit() {
this.displayMessage = errorMessage(error);
}
}
For further reading, always consult the Angular Documentation or Angular Github Repo.