I'm running into a problem with a null value (instead of an array of Lectures) being passed to a pipe when using the safe navigation operator on an async loaded observable:
<div *ngFor="let lecture of ((lecturesObservable | async)?.lectures | lectureType: 'main')" class="list-group-item">
lecture-type.pipe.ts
import { Pipe, PipeTransform } from '@angular/core';
import { Lecture } from './lecture';
@Pipe({name: 'lectureType'})
export class LectureTypePipe implements PipeTransform {
transform(allLectures: Lecture[], lectureType: string): Lecture[]{
return allLectures.filter(lecture => lecture.type==lectureType);
}
}
The lectures are iterated through fine without the pipe, once they are loaded by async. Is this just something I have to live with in ng2?
The Angular safe navigation operator, ? , guards against null and undefined values in property paths. Here, it protects against a view render failure if item is null .
We can use the async pipe in Angular application by including the CommonModule which exports all the basic Angular directives and pipes, such as NgIf, NgForOf, DecimalPipe, and so on.
Angular's async pipe is a tool to resolve the value of a subscribable in the template. A subscribable can be an Observable , an EventEmitter , or a Promise . The pipe listens for promises to resolve and observables and event emitters to emit values.
Angular expects pipes to be synchronous. They should return a resolved value, not a Promise or an Observable . To use a pipe that returns an unresolved value, you can use Angular's async pipe. If that's not an option, you can resolve the asynchronous value inside the pipe if you make it impure, as I describe below.
The async pipe resolves to null by design when its input observable does not yet have a value. So yes, you will have to live with it, by designing your pipe to handle a null input.
You can also hide the block completely with an *ngIf
, and put the async pipe there instead.
Note the important addition of let
to assign to a locally scoped variable.
In your *ngFor
you use that newlectures
variable and it's guaranteed to always have a value - so your pipe won't see empty values.
Plus you get a 'Loading template' for 'free'
<div *ngIf="(lecturesObservable | async)?.lectures; let lectures; else loadingLectures">
<div *ngFor="let lecture of (lectures | lectureType: 'main')" class="list-group-item">
Lecture details...
</div>
</div>
<ng-template #loadingLectures>
Loading lectures!
</ng-template>
Also note that *ngIf
can be used on <ng-container>
which adds nothing to the DOM.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With