Pure vs impure pipes
When building a custom pipe you can specify whether you define a pure or an impure pipe. By default, the pipe is pure i.e. pure: true
@Pipe({
name: 'demoPipe',
pure: false/true
})
export class DemoPipe { }
Pure pipes
Pure pipes are the pipes that execute when it detects a pure change in the input value.
A pure change is when the change detection cycle detects a change to either a primitive input value (such as String, Number, Boolean, or Symbol) or object reference (such as Date, Array, Function, or Object).
Impure pipes
Impure pipes are the pipes that execute when it detects an impure change in the input value.
An impure change is when the change detection cycle detects a change to composite objects, such as adding an element to the existing array. Let’s take the same example that we took earlier.
ReversePipe
that we built earlier is a pure pipe. It will only execute if it detects a change in the user’s object reference.
Create new pipe
ng generate pipe pipes/impureDemo --standalone --skip-tests=true
@Pipe({
name: 'impureDemo',
standalone: true
})
export class ImpureDemoPipe implements PipeTransform {
transform(value: Object): void {
console.log(JSON.stringify(value));
}
}
<!-- card.component.html -->
<mat-card class="card">
<mat-card-header>
<mat-card-title>{{title | uppercase | reverse}}</mat-card-title>
<mat-card-subtitle>{{likeCount}} Likes</mat-card-subtitle>
</mat-card-header>
<img mat-card-image [src]="imageUrl" alt="shiba">
<mat-card-content>
<p>I am {{'running'}} on port {{port}}</p>
<p>The hero's birthday is {{ birthday | date:"MM/dd/yy" }} </p>
<p>Server: {{server | impureDemo }}</p>
<p [style.fontSize]="size">Server with Id {{server.id}} is {{server.status}}</p>
<!-- <p [style]="style">Server status from method: {{getServerStatus()}}</p> -->
<mat-form-field appearance="fill">
<mat-label>Title</mat-label>
<input matInput [(ngModel)]="title">
</mat-form-field>
</mat-card-content>
<mat-card-actions>
<button mat-button [disabled]="isLikeDisabled" (click)="onLike()">LIKE</button>
<button mat-button [disabled]="isShareDisabled">SHARE</button>
<button mat-button (click)="toggleStatus()">Change Status</button>
</mat-card-actions>
</mat-card>
What will happen if we change the property of server.status
?
@Component({
selector: 'app-card',
standalone: true,
templateUrl: './card.component.html',
styleUrls: ['./card.component.scss'],
imports: [CommonModule, MatCardModule, MatButtonModule, MatFormFieldModule, MatInputModule, FormsModule, ReversePipe, ImpureDemoPipe]
})
export class CardComponent {
toggleStatus(): void {
this.server.status = this.server.status === 'offline' ? 'online' : 'offline';
}
}
The impureDemo
doesn’t log anything. Now change pure:false
. Voila! Everything works as expected.
pure:true
didn’t execute log because even if the property has changed because the object reference is still the same. To detect this change, Angular will have to do a deep check for differences within the object. Also, this change is not pure; the pipe ignores the changes within objects.
A single instance of pipe is used all over the component.
A pure must use a pure function.
A pure function does not depend on any state, data, or change during the execution. In other words, given the same arguments, a pure function should always return the same output.