Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Safe navigation operator on an async observable and pipe in Angular 2

Tags:

angular

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?

like image 894
theotherdy Avatar asked Aug 03 '16 19:08

theotherdy


People also ask

What is safe navigation operator in Angular?

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 .

What type of data works with async pipe in Angular?

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.

What is the purpose of Asyncpipe in Angular?

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.

Can Angular pipe return Observable?

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.


2 Answers

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.

like image 185
Douglas Avatar answered Oct 03 '22 01:10

Douglas


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.

like image 34
Simon_Weaver Avatar answered Oct 03 '22 00:10

Simon_Weaver