Home > Blockchain >  ngFor JSON array of object async await angular 13 not binding
ngFor JSON array of object async await angular 13 not binding

Time:03-14

Here is my typescript page.

export class ListUsersComponent implements OnInit {
  users: any;
  constructor(){}

  async ngOnInit() {
    await this.loadUser();
  }

  async loadUser() {
      const us = this.userService.getUsers().pipe(
       first(),
      catchError((errorMessage) => {
        return of(EMPTY_UserProfile);
      })
).subscribe((data: any) => {
  this.users = data;
  console.log(this.users);
});
this.subscriptions.push(us);
  }
}

As the this.user bind easily, it gives me result as

[
  {
    "id": 1,
    "userName": "xyz",
  },
  {
    "id": 2,
    "userName": "xyz2",
  }
]

Here is the HTML ngFor.

<tr align="center" *ngFor="let user of users | async; let i=index">
     <td>{{user.id}}</td>
     <td>{{user.userName}} </td>
</tr>

There is no output shown as I tried every possible way I found through articles. It works when I try to call a fixed Array JSON object in the constructor but calling async await in ngOnInit doesn't really help me. I might be missing something?

Update 1:

Here is the observable part where service is being called.

    getUsers(id?: string): Observable<UserDetails> {
    const auth = this.getAuthFromLocalStorage();
    if (!auth || !auth.authToken) {
      return of(undefined);
    }

    this.isLoadingSubject.next(true);
    return this.userHttpService.getUsers(auth.authToken, '').pipe(
      map((user: UserDetails) => {
        if (user) {
          this.currentUsers = new BehaviorSubject<UserDetails>(user);
        } else {
          this.logout();
        }
        return user;
      }),
      finalize(() => this.isLoadingSubject.next(false))
    );
  }

Update 2: this calls from Update 1 as this.userHttpService.getUsers(auth.authToken, '')

getUsers(token, Id?: string): Observable<UserDetails> {
    const httpHeaders = new HttpHeaders({
      Authorization: `Bearer ${token}`,
    });
    return this.http.get<UserDetails>(`${API_URL}/GetCompanyUsers?Id=`   Id   `&pageNumber=1`   `&pageSize=1`, {
      headers: httpHeaders,
    });
  }

CodePudding user response:

A couple of things here.

  1. No need to add async await here as GRD also said in the comment.
  2. you already subscribing so no need to use the async pipe.

Note: if you are directly using observable then use async pipe.

  users: any[] = [];
  constructor(){}

  ngOnInit() {
    this.loadUser();
  }

  loadUser() {
      const sb = this.userService.getUserProfile().pipe(
       first(),
       catchError((errorMessage) => {
        return of(EMPTY_UserProfile);
       })
      ).subscribe((users: UserProfile[]) => {
      this.users = users; //data is recieved but not shown on ngFor HTML page
    });
    this.subscriptions.push(sb);
  }
}
<tr align="center" *ngFor="let user of users; let i=index">
     <td>{{user.id}}</td>
     <td>{{user.userName}} </td>
</tr>

CodePudding user response:

As the async pipe definition states

The async pipe subscribes to an Observable or Promise and returns the latest value it has emitted.

You'll need to apply async pipe, if you are binding to an observable, in your case in the loadUser() method you are subscribing to an observable and hence no need to use async pipe.

If you want to apply async pipe, then modify the loadUser method like this

  loadUser():Observable<any[]> {
  const sb = this.userService.getUserProfile().pipe(
   first(),
   catchError((errorMessage) => {
    return of(EMPTY_UserProfile);
   })
  );
this.subscriptions.push(sb);
return sb;
 }

and then you'll have to modify the *ngFor like this

<tr align="center" *ngFor="let user of loadUser() | async; let i=index">
 <td>{{user.id}}</td>
 <td>{{user.userName}} </td>
</tr>
  • Related