angulartypescriptobservableasync-pipe

Angular Keyvalue pipe for nested object


I have http request that returns an observable object of objects. it contains many properities. one of them is 'weight' object that contains two keyvalues, imperial and metric.

I am trying to loop over the keyvalues of the object but I am having issues rending the nested objects, it just shows

weight [object object]

my code

<div style=" margin : auto; border : 1px solid black; width : 70%; ">
<div style="display : flex;  justify-content : space-around; flex-wrap:wrap;">
  <div *ngFor="let breed of (breeds$ | async )" style="flex : 33%">
  <div *ngFor="let item of (breed | keyvalue : unsorted)">
    <div *ngIf="item.key === 'weight'">
      {{breed.weight.imperial}}
    </div>
    <b>{{item.key}}</b>{{item.value}}
  </div>
  </div>
</div>

my approach is just explicit

    <div *ngIf="item.key === 'weight'">
      {{breed.weight.imperial}}
    </div>

and doesn't work for other objects contained in the observable, and I think it is not really a good approach to the problem.

an example of data returned by the observable

    {
        "weight": {
            "imperial": "7  -  10",
            "metric": "3 - 5"
        },
        "id": "abys",
        "name": "Abyssinian",
        "image": {
            "id": "0XYvRd7oD",
            "width": 1204,
            "height": 1445,
            "url": "https://cdn2.thecatapi.com/images/0XYvRd7oD.jpg"
        }
    }

I tried replacing my explicit approach with

<div *ngIf="item.key === 'weight'">
<div *ngFor="let data of item.value">{{data.imperial}}</div>
</div>

but it shows this error

Type 'string | number | { imperial: string; metric: string; } | { id: string; width: number; height: number; url: string; }' is not assignable to type '(string & NgIterable<string>) | null | undefined'.ngtsc(2322)

Solution

  • As the weight is an object, you need to apply keyvalue pipe to make it iterable.

    <div *ngFor="let data of item.value | keyvalue">
      <span>{{ data.key }}</span>: <span>{{ data.value }}</span>
    </div>
    

    Demo @ StackBltz