Search code examples
angulartypescriptangular13

ngFor JSON array of object async await angular 13 not binding


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,
    });
  }

Solution

  • 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.getUsers().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>