JustinM
JustinM

Reputation: 1013

ngIf with condition loses original object for let binding; with async pipe

Suppose I am tracking the currently logged in user like this. If the user is null, they aren't logged in. If logged in, they are either anonymous (no name) or not.

interface User {
  name?: string;
}

currentUser$: Observable<User>;

Now suppose I want to display something if the user is not anonymous, like this...

<div *ngIf="(this.currentUser$ | async)?.name != null; let user">
    Hello {{user.name}}
</div>

This does NOT work because the user variable gets bound to a boolean, not to the original user from the async pipe. Likewise I can't use *ngIf to find the logged in users - anonymous or not - since as soon as I run the condition (this.currentUser$ | async) != null; let user I no longer have access to the user object to use in the template.

I tried something like this...

<ng-container *ngIf="this.currentUser$ | async; let user">
    <div *ngIf="user === 'none'">Need to sign in</div>
    <div *ngIf="user !== 'none' && user.name==null">Hi stranger</div>
    <div *ngIf="user !== 'none' && user.name!=null">Hi {{user.name}}</div>
</ng-container>

But this doesn't work either. First, I need to convert my observable to one where null gets swapped with something else, like -1 or the string none, because I'm pretty sure otherwise the *ngIf will return false. And then the user.name==null part won't compile since Angular still thinks the variable is a User | 'none', not just a User. I wasn't able to figure out how to cast it to make the error go away.

I think I can do most of what I want by subscribing to the observable in my component, storing the current user details as a variable or two, and then using {{currentUser}} in the template. This is a bunch of extra work and I need to remember to unsubscribe. Kind of defeats the coolness of the async pipe.

What am I missing here? I'm coming from a asp.net Razor background where you can define temp variables inside the template and I guess I want to do something similar here.

Upvotes: 0

Views: 2193

Answers (1)

Nadhir Falta
Nadhir Falta

Reputation: 5257

Couple things: first remove this from your html, that's not needed.
Secondly, you can do: (this.currentUser$ | async) as user

<div *ngIf="(this.currentUser$ | async) as user">
    <span *ngIf="user.name">Hello {{user.name}}</span>
</div>

Upvotes: 3

Related Questions