Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular async pipe and object property

I need to use async pipe without ngFor. I need to check property of object that is async loaded with observable.

This is what i want, but not working:

 <ion-item *ngIf="user$.anonymouse | async">      <ion-label>Login</ion-label>  </ion-item> 

//EDIT: I getting this error when i use code above

EXCEPTION: Invalid argument 'true' for pipe 'AsyncPipe' in [!user$.anonymouse | async in SettingsPage@27:22]

Is there any way how to solve this?

I know i can subscribe to this observable in Ctrl a store values into normal variable but i dont want to do that, because of perfomance etc.

like image 874
Daniel Suchý Avatar asked May 10 '16 14:05

Daniel Suchý


People also ask

What is the purpose of async pipe in angular?

The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted. When a new value is emitted, the async pipe marks the component to be checked for changes. When the component gets destroyed, the async pipe unsubscribes automatically to avoid potential memory leaks.

Why async pipe is impure?

Because of the way Promise s work, Angular's async pipe has to be impure (meaning that it can return different outputs without any change in input). The transform method on Pipe s is synchronous, so when an async pipe gets a Promise , the pipe adds a callback to the Promise and returns null.

What kind of data can be used with async pipe?

With AsyncPipe we can use promises and observables directly in our template, without having to store the result on an intermediate property or variable.

What does async pipe return?

Angular's async pipe is a pipe that subscribes to an Observable or Promise for you and returns the last value that was emitted.


2 Answers

The error is surprisingly accurate as the *ngIf directive expects true or false and uses the resulting expression to determine whether or not to render the HTML element in the DOM.

EXCEPTION: Invalid argument 'true' for pipe 'AsyncPipe' in [!user$.anonymouse | async in SettingsPage@27:22]

The expression you have is user$.anonymouse which evaluates as truthy, but unfortunately you cannot use the async pipe with this directive. The async pipe "transforms" (also known as "pipes") the input exposing the resulting output within the scope of the *ngFor directive for example.

The pipe expects one of three possible types, defined below (detailed about AsyncPipe):

transform(obj: Observable<any>| Promise<any>| EventEmitter<any>)

Is there any way how to solve this?

Yes, you can either use it as it was designed. For example in an *ngFor directive:

<ion-item *ngFor="(user$ | async)?.anonymouse">      <ion-label>Login</ion-label> </ion-item> 

Or you could remove the piping altogether as it's not needed for the *ngIf directive:

<ion-item *ngIf="user$.anonymouse">      <ion-label>Login</ion-label> </ion-item> 
like image 67
David Pine Avatar answered Oct 13 '22 01:10

David Pine


As stated in the comments by @Sean, your *ngIf statement should be based on the resulted object property anonymouse of the user$ object that is returned. As such:

<ion-item *ngIf="(user$ | async)?.anonymouse">      <ion-label>Login</ion-label> </ion-item> 

This worked for me and here is an example of how to use the results from the pipe below:

Component

 message$: Observable<{message: string}>;    private messages = [     {message: 'You are my hero!'},     {message: 'You are the best hero!'},     {message: 'Will you be my hero?'}   ];    constructor() { this.resend(); }    resend() {     this.message$ = Observable.interval(500)       .map(i => this.messages[i])       .take(this.messages.length);   } 

View

<h2>Async Hero Message and AsyncPipe</h2> <p>Message: {{ (message$ | async)?.message }}</p> <button (click)="resend()">Resend</button>` 

A working example can be found here.

like image 36
Abdullah Rasheed Avatar answered Oct 13 '22 01:10

Abdullah Rasheed