4

I am using async pipe in my template for an Observable:

applicants$: Observable<UserProfile[]>;
  ngOnInit() {
    this.applicants$ = this.store.pipe(
      select(fromRootUserProfileState.getUserProfiles)
    ) as Observable<UserProfile[]>;
}

Here is UserProfile.ts interface:

import { Role } from './role/role';
import { Country } from './Country';

export interface UserProfile {
  id?: number;
  fullName?: string;
  roles?: Role[];
  windowsAccount?: string;
  firstName?: string;
  lastName?: string;
  email?: string;
  managerName?: string;
  managerId?: number;
  managerEmail?: string;
  companyId?: number;
  companyName?: string;
  countryId?: number;
  country?: Country;
  countryName?: string;
}

And here is the userProfile.service

  getUserProfiles(): Observable<UserProfile[]> {
    return this.http.get<UserProfile[]>(
      this.baseUrl + 'userprofiles/getuserprofiles'
    );
  }

In the template I've used ngFor to iterate through the Observable with an async pipe:

<mat-form-field
  fxFlex="22"
  appearance="outline"
  *ngIf="applicants$ | async as applicants"
>
  <mat-label>Applicant</mat-label>
  <mat-icon matPrefix>person</mat-icon>
  <mat-select
    placeholder="Applicant"
    name="applicant"
    [(ngModel)]="this.searchPurchaseOrder.applicantId"
  >
    <mat-option *ngFor="let ap of applicants" [value]="ap.id">
      ap.fullName
    </mat-option>
  </mat-select>
</mat-form-field>

However, here is the error I am getting: enter image description here

Here is the data shape from the store. It is being populated, so there is no problem there: enter image description here

Efron A.
  • 353
  • 3
  • 10
  • 19

5 Answers5

8

You will need to use the keyvalue pipe to loop through your object as if it were an array.

https://angular.io/api/common/KeyValuePipe

<div *ngFor="let applicant of applicants | keyvalue">
  {{applicant.key}}:{{applicant.value}}
</div>

This can work with the async pipe too, e.g:

<div *ngFor="let item of (object$ | async) | keyvalue">
Matt Saunders
  • 3,538
  • 2
  • 22
  • 30
1

The problem here is that you are trying to use ngFor to loop through an object (Which is not possible). If you can post a preview of the response from the network tab it would be helpful to get a better idea about the matter.

1

Thanks to Matt Saunders' answer this change to the template has worked for my case:

<mat-form-field
  fxFlex="22"
  appearance="outline"
  *ngIf="this.applicants$ | async | keyvalue as applicants">
  <mat-label>Applicant</mat-label>
  <mat-icon matPrefix>person</mat-icon>
  <mat-select
    placeholder="Applicant"
    name="applicant"
    [(ngModel)]="this.searchPurchaseOrder.applicantId">
    <mat-option
      *ngFor="let applicant of applicants"
      [value]="applicant.value.id">
      {{ applicant.value.fullName }}
    </mat-option>
  </mat-select>
</mat-form-field>
Efron A.
  • 353
  • 3
  • 10
  • 19
0

Try using the pipe with the alias also: let ap of applicants | async.

E. Mancebo
  • 629
  • 3
  • 10
  • Async pipe has already been applied beforehand. If I use it as you said I get this error: ERROR Error: InvalidPipeArgument: '[object Object]' for pipe 'AsyncPipe' – Efron A. Apr 26 '20 at 09:28
0

Well if you getting the data from backend..... Like node Mongo then follow this approach

res.status().json({ data: [yourdata] })

Now you don't need to do anything.

Happy codding.

Ali Esmailpor
  • 1,209
  • 3
  • 11
  • 22