0

in this Angular component, I get an observable of user object, I try to verify on NgInit, whether the profile picture URL is defined. If not, I want to set a placeholder for that. But for some reason, the change I make within ngOnInit is too late. The image source is not set properly, so the result is the alternative text is being displayed. I thought the async pipe will help me to get the image whenever it is newly set? Could someone help me to get a better understanding for this context? :)

  @Input()
  user$: Observable<UserProfileData>;

  userSub: Subscription;

  constructor() { }

  ngOnDestroy(): void {
    this.userSub.unsubscribe();
  }

  ngOnInit(): void {
    this.userSub = this.user$.subscribe(user=> {
      user.profilePictureUrl = (user.profilePictureUrl) ? user.profilePictureUrl : '/assets/placeholder.png';
      }
    )
  }

And in HTML, I simply call the user profile picture with async pipe.

<img class="ml-lg-5 mb-2 mb-md-0 mx-auto rounded-circle" src="{{(user$|async).profilePictureUrl}}" alt="{{ (user$|async).username }}">

This is what I get for user$, it is from an object of UserProfileData:

description: "My name is Steve, I look forward to collaborating with you guys!"
firstname: "Steve"
lastname: "Mustermann"
location: LocationModel {country: "Germany", city: "Hamburg", zipcode: "22145"}
occupation: "Barber"
profilePictureUrl: ""
score: "69.1"
username: "steve669"
10
  • Why are you subscribing to the observable user$ both in the component and template?
    – Nicholas K
    Commented Dec 12, 2020 at 10:26
  • is there a way to subscribe in only one place? Feel free to share your approach with me :)
    – user10229833
    Commented Dec 12, 2020 at 10:27
  • Yeah. You can choose to do it in either of the places and not both.
    – Nicholas K
    Commented Dec 12, 2020 at 10:28
  • Also, can you share what user$ returns after subscription?
    – Nicholas K
    Commented Dec 12, 2020 at 10:29
  • if i only want to subscribe in the component, how would I declare it in the template?
    – user10229833
    Commented Dec 12, 2020 at 10:30

1 Answer 1

0

You can do it like this

ngOnInit(): void {
  this.user$ = this.user$.pipe(map(user => {
    if (!user.profilePictureUrl) {
      user.profilePictureUrl = '/assets/placeholder.png';
    }

    return user;
  }));
)

In the template

<ng-container *ngIf="user$ | async as user">
  <img class="ml-lg-5 mb-2 mb-md-0 mx-auto rounded-circle" src="{{user.profilePictureUrl}}" alt="{{ user.username }}">
</ng-container>
2
  • Hi! thank you so much for this working solution! I have read that .subscribe() doesn't work out with the onPush change detection strategy ootb, but if I'd follow the subscribe approach, how would i make it work too?
    – user10229833
    Commented Dec 12, 2020 at 10:45
  • ` public user: UserProfileData; ngOnInit(): void { this.user$.subscribe((user => { if (!user.profilePictureUrl) { user.profilePictureUrl = '/assets/placeholder.png'; } this.user = user; })); ) ` In template ` <img class="ml-lg-5 mb-2 mb-md-0 mx-auto rounded-circle" src="{{user.profilePictureUrl}}" alt="{{ user.username }}"> `
    – Hoang NK
    Commented Dec 12, 2020 at 10:49