9

I use github API to load user and his followers data in my angular 2 app, but view renders before ngOnInit finishes load data and because of this I receive: Cannot read property of undefined error. My code fragment looks like this:

ngOnInit() {
    Observable.forkJoin(
        this._githubService.getUser('kaxi1993'),
        this._githubService.getFollowers('kaxi1993')
    )
    .subscribe(res => {
        this.user = res[0];
        this.followers = res[1];
    },
    null,
    () => {
        this.isLoading = false;
    });
}

if I write html code like this:

 <div *ngIf="user && user.avatar_url">
   <img class="media-object avatar" [src]="user.avatar_url" alt="...">
 </div>

works fine, but returns error Cannot read property 'avatar_url' of undefined when write html code without *ngIf like this:

<img class="media-object avatar" [src]="user.avatar_url" alt="...">

also note: getFollowers works fine, but if I move getFollowers before getUsers in forkJoin method then getUsers works fine and getFollowers need *ngIf to avoid error. Is it possible to write without extra *ngIf code? any help guys, Thanks a lot.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
kaxi1993
  • 4,535
  • 4
  • 29
  • 47
  • The accepted answer only talks about avoiding the error. If you want to solve the root cause you can use a `resolver` for getting the API data before your component initializes. Check out [this](https://shermandigital.com/blog/wait-for-data-before-rendering-views-in-angular-2/) article. – Voicu Jan 19 '18 at 06:51

1 Answers1

11

You can use the safe-navigation (Elvis) operator to avoid the error like

 <div *ngIf="user?.avatar_url">
   <img class="media-object avatar" [src]="user.avatar_url" alt="...">
 </div>

or

<img class="media-object avatar" [src]="user?.avatar_url" alt="...">
Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 2
    thank you for your answer, upvoted, but I'm interested is it ok when view renders before data loads in ngOnInit? – kaxi1993 Jun 01 '16 at 09:59
  • 4
    That's normal behavior. The call to the server can take "ages". Angular just renders the view when the component is created and updates it when data arrives (when the model is updated). There are feature requests for a lifecycle callback that waits for the template to render until a promise resolves but currently this is not supported. – Günter Zöchbauer Jun 01 '16 at 10:01
  • 1
    Ok thank you, wish you good lucks ;) – kaxi1993 Jun 01 '16 at 10:04
  • 1
    This saved my bacon, but it blows that it works that way. Thus is life – Maccurt Oct 29 '17 at 00:52