htmlangulartypescriptrxjsangular-httpclient

Angular displaying Observable Array


I have an API (Node.js) and an Angular frontend.

Now I want to loop through the data and display it. Therefore I perform an HTTP Request to the backend and get back an Observable which i then want to display on the screen.

The code to display:

<ng-container *ngFor="let p of plans$ | async">
    <a [routerLink]="['/plan', p.id]">

        <div class="plan" style="margin-bottom: 10px;">
            <div class="row">
                <div class="col-md-2">
                    <img [src]="p.image" style="margin: 5px;"/>
                </div>
                <div class="col-md-10" style="padding-top: 5px;">
                    <div class="title">{{ p.name }}</div>
                    <div class="description">{{ p.description }}</div>
                    <div class="description">Übungen: {{ p.exercises }}</div>
                </div>
            </div>
        </div>
    </a>
</ng-container>

The corresponding service:

  fetchAll(): Observable<Plan[]> {
    return this.http
      .get<Plan[]>(this.url, { responseType: "json" })
      .pipe(
        catchError(this.errorHandlerService.handleError<Plan[]>("fetchAll"))
      );
  }

But somehow I get the following error:

ERROR RuntimeError: NG02200: Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables, such as Arrays. Did you mean to use the keyvalue pipe? Find more at

What am I missing?

Edit:

{
"plans": [
    {
        "id": 1,
        "name": "Plan 1",
        "description": "Super lange Text",
        "image": "assets/workout_15620186.png",
        "exercises": 11
    },
    {
        "id": 2,
        "name": "Plan 2",
        "description": "Super lange Text",
        "image": "assets/workout_15620186.png",
        "exercises": 1
    },
    {
        "id": 3,
        "name": "Plan 3",
        "description": "Super lange Text",
        "image": "assets/workout_15620186.png",
        "exercises": 1
    }
]
}

Solution

  • You have to access the plans array inside the API response.

    When you try to pass in an object to ngFor we will get this error, because it expects an array to iterate, looking at your API response, we have to access the property plans which contains the array that you want to iterate.


    Use map of rxjs to access the inner plans array.

    fetchAll(): Observable<Plan[]> {
        return this.http
          .get<Plan[]>(this.url, { responseType: "json" })
          .pipe(
            map((data:any) => data.plans),
            catchError(this.errorHandlerService.handleError<Plan[]>("fetchAll"))
          );
      }
    

    OR


    Access the array form the html.

    HTML

    <ng-container *ngFor="let p of (plans$ | async).plans">
        <a [routerLink]="['/plan', p.id]">
            <div class="plan" style="margin-bottom: 10px;">
                <div class="row">
                    <div class="col-md-2">
                        <img [src]="p.image" style="margin: 5px;"/>
                    </div>
                    <div class="col-md-10" style="padding-top: 5px;">
                        <div class="title">{{ p.name }}</div>
                        <div class="description">{{ p.description }}</div>
                        <div class="description">Übungen: {{ p.exercises }}</div>
                    </div>
                </div>
            </div>
        </a>
    </ng-container>