Umair Jameel
Umair Jameel

Reputation: 1673

Load the data before template render in Angular

I am using Angular 6 and using one way binding.

My code in component is given below.

ngOnInit() {
 this.profile.getUser(1).subscribe((data) => {
  this.userData = this.compiler.constructUserData(data);
 });
}

userData has one object and it has properties. I am trying to bind its data in HTML as shown below

<mat-list-item role="listitem">
          <span matLine>
            <span>First Name: </span>
            <span> {{userData?.first_name}}</span>
          </span>
        </mat-list-item>
        <mat-list-item role="listitem">
          <span matLine>
            <span>Last Name: </span>
            <span> {{userData?.last_name}} </span>
          </span>
        </mat-list-item>
        <mat-list-item role="listitem">
          <span matLine>
            <span>Email: </span>
            <span> {{userData?.email}} </span>
          </span>
        </mat-list-item>
        <mat-list-item role="listitem">
          <span matLine>
            <span>Mobile: </span>
            <span> {{userData.mobile_no}} </span>
          </span>
        </mat-list-item>

here I have used ? after userData variable. But when I write ? with last item as well

e.g. mobile_no it doesn't show any of the data (first_name, last_name, email or mobile_no) on the web. But if I remove ? from last item or any of the item. Data shows up but in console of web page.

Errors shows up as shown below.

Error description

Upvotes: 3

Views: 4825

Answers (1)

SiddAjmera
SiddAjmera

Reputation: 39452

If you're subscribing to the Observable and not placing a ? in the template, make sure to initialize the this.userData with an empty Object initially.

Something like this:

userData = {};

I'd recommend you to rather use the async pipe in the template and not subscribe to the Observable. Assuming that you'll get the userData as an Object containing email, first_name, etc. in your userData Object, this would look something like this:

import { map } from 'rxjs/operators';

...

userData$;

...

ngOnInit() {
  this.userData$ = this.profile.getUser(1).pipe(
    map(data => {
      return this.compiler.constructUserData(data);
    })
  );
}

And in your template:

<div *ngIf="userData$ | async as userData">
  <mat-list-item role="listitem">
    <span matLine>
            <span>First Name: </span>
    <span> {{userData.first_name}}</span>
    </span>
  </mat-list-item>
  <mat-list-item role="listitem">
    <span matLine>
            <span>Last Name: </span>
    <span> {{userData.last_name}} </span>
    </span>
  </mat-list-item>
  <mat-list-item role="listitem">
    <span matLine>
            <span>Email: </span>
    <span> {{userData.email}} </span>
    </span>
  </mat-list-item>
  <mat-list-item role="listitem">
    <span matLine>
            <span>Mobile: </span>
    <span> {{userData.mobile_no}} </span>
    </span>
  </mat-list-item>
</div>

Here's a Working Sample StackBlitz for your ref.

Upvotes: 3

Related Questions