Two ways of using AsyncPipe programmatically
danielpdev
Posted on March 2, 2020
What is AsyncPipe?
AsyncPipe is an angular pipe that helps you resolve an asynchronous value(like an observable or a promise) to a primitive one.
Common use cases of using AsyncPipe:
Being a pipe it's mostly used on HTML.
Do I need to subscribe/unsubscribe when I use the AsyncPipe on HTML?
No, the implementation of AsyncPipe will take care of subscribing and unsubscribing.
How can I use AsyncPipe programmatically in my custom pipes?
Here you can find two ways of using AsyncPipe in your custom pipes:
1. Providing AsyncPipe
and ChangeDetectorRef
to Dependancy Injection (DI) in your module
You might think that it will just work if you let Dependancy Injection (DI) do the work for you:
@Pipe({ name: "my_async_pipe" })
export class MyAsyncPipe implements PipeTransform {
constructor(private asyncPipe: AsyncPipe) {}
transform(value: any): any {
return this.asyncPipe.transform(value);
}
}
Above code will not work and will throw an error like:
ERROR NullInjectorError: StaticInjectorError(AppModule)[ErrorAsyncPipe -> AsyncPipe]:
StaticInjectorError(Platform: core)[ErrorAsyncPipe -> AsyncPipe]:
NullInjectorError: No provider for AsyncPipe!
Hmmm seams like AsyncPipe
has not be added to providers array. Let's fix this error:
- Go to
app.module.ts
- Add providers: [AsyncPipe]
- reload
ERROR NullInjectorError: StaticInjectorError(AppModule)[AsyncPipe -> ChangeDetectorRef]:
StaticInjectorError(Platform: core)[AsyncPipe -> ChangeDetectorRef]:
NullInjectorError: No provider for ChangeDetectorRef!
Another injector not provided, let's repeat the steps above, but this time add ChangeDetectorRef as Provider
:
- Go to
app.module.ts
- This time add providers: [AsyncPipe, ChangeDetectorRef as Provider]
- reload
Success, AsyncPipe has been successfully provided for your custom Pipe.
2. Creating a new AsyncPipe
instance
@Pipe({ name: "cdr_async_pipe" })
export class CdrAsyncPipe implements PipeTransform {
private asyncPipe: AsyncPipe;
constructor(private cdr: ChangeDetectorRef) {
this.asyncPipe = new AsyncPipe(this.cdr);
}
transform(value: any): any {
return this.asyncPipe.transform(value);
}
ngOnDestroy() {
this.asyncPipe.ngOnDestroy();
}
}
Using:
constructor(private cdr: ChangeDetectorRef) {
this.asyncPipe = new AsyncPipe(this.cdr);
}
The code above creates an instance of AsyncPipe by passing the ChangeDetectorRef as argument.
If you do create your own AsyncPipe
manually then please don't forget to call ngOnDestroy()
lifecycle method.
Which is the best way to use AsyncPipe
programmatically in your custom pipes?
In my opinion the second one is the best because DI
will not create two instances of ChangeDetectionRef
thus no errors like this._ref.markForChek() is not a function
will be thrown as ChangeDetectionRef
will be created with one of the classes that extends it.
In the next articles we will look at why when we declare ChangeDetectionRef
as a provider we get the error this._ref.markForChek() is not a function
.
Article first posted on danielpdev.io
Posted on March 2, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.