Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if Observable is undefined

On an Angular 7 application I have the following template:

<div *ngIf="avatarUrl$ | async;">
  <ng-container *ngIf="avatarUrl$ | async as avatarUrl">
    <img [src]="avatarUrl ? avatarUrl : 'avatar-default.png'">
  </ng-container>
</div>

The avatarUrl$ is an observable as is obtained from a database through a service.

I want to display the IMG only after avatarUrl$ has a value loaded.

However, sometimes that value obtained from the service is undefined.

In that case I need to display the default avatar, e.g: avatar-default.png.

The problem is that avatar-default.png is not displayed when avatarUrl$ is undefined.

I think because of this condition that does not differentiate from the value not being loaded and being loaded but is undefined?

<div *ngIf="avatarUrl$ | async;">

How can I solve this?

like image 553
Miguel Moura Avatar asked Jun 07 '26 03:06

Miguel Moura


2 Answers

Seems a bit redundant, you can do just this:

<div>
  <img [src]="(avatarUrl$ | async) || 'avatar-default.png'">
</div>

Or change your observable in your component:

readonly avatarUrl$ = this.getAvatarFromSomeWhere().pipe(
  startWith('avatar-default.png')
);

<div>
  <img [src]="avatarUrl$ | async">
</div>

Then you don't need to do any || and just keep the template simple. This way only works when you are sure the request will return an avatar eventually

Otherwise you can expand a bit on it using map which will make sure it will always return a value:

private readonly defaultAvatar = 'avatar-default.png';

readonly avatarUrl$ = this.getAvatarFromSomeWhere().pipe(
  map((avatar) => avatar || this.defaultAvatar),
  startWith(this.defaultAvatar)
);

edit

@C_Ogoo is right, I should have read better.

In the case you want it to only show after it has been loaded, you just need to change the observable like this:

readonly avatarUrl$ = this.getAvatarFromSomeWhere().pipe(
  map((avatar) => avatar || 'avatar-default.png')
);

and you can do the template like:

template

<div *ngIf="avatarUrl$ | async as avatarUrl">
  <img [src]="avatarUrl">
</div>
like image 138
Poul Kruijt Avatar answered Jun 10 '26 18:06

Poul Kruijt


You can achieve that with object of observable. It is usefull when you want the value null, undefined or 0 from your observable not to be blocked in the *ngIf

<div *ngIf="{url: avatarUrl$ | async} as data">
    <img [src]="data.url ? data.url : 'avatar-default.png'">
</div>

It's good to know, that you can have multiple observables in your object if you want:

<div *ngIf="{url: avatarUrl$ | async, picture: pictureUrl$ | async} as data">
...
</div>
like image 27
Wandrille Avatar answered Jun 10 '26 17:06

Wandrille



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!