1

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)
1
  • You should use the "iterate variable" item, not "bread": {{item.value.weight.imperial}} Commented Dec 23, 2022 at 7:26

3 Answers 3

1

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

Sign up to request clarification or add additional context in comments.

6 Comments

it still produces this error Argument of type 'string | number | { imperial: string; metric: string; } | { id: string; width: number; height: number; url: string; }' is not assignable to parameter of type 'Record<string, string | number | (() => string) | ((pos: number) => string) | ((index: number) => number) | ((...strings: string[]) => string) | ((searchString: string, position?: number | undefined) => number) | ... 43 more ... | (() => IterableIterator<...>)> | ReadonlyMap<...> | null | undefined'.ngtsc(2769) on item.value of this iteration
The latest error message is different from the previous error message. Can you create a demo in StackBlitz to reproduce the error mentioned? Thanks.
Thanks for follow up; is this link working ? Demo
Look like you need $any method to escape the type checking. Demo
Because when you pass item.value in *ngFor, TypeScript detects it is either of these types as mentioned in your attached error message. The type such as string and number is not iterable. $any is the way to prevent performing type checking. Best practise? Depends on your case. From my perspective, I will specify the property that I want to be displayed instead of using *ngFor. Using *ngFor is convenient if you want to display all properties without the worry of customization.
|
1

Face the same problem, and I just solved it.

See this stackblitz for a reference.

Write a compareFn for keyValue and wrap parament type, like KeyValue<string, any>

in typescript

  ...

  sortByValueAsc = (a: KeyValue<string, any>, b: KeyValue<string, any>) => {
    return 0
  };

and in HTML

<td *ngFor="let answer of surveyDetail.answer | keyvalue:sortByValueAsc">{{answer.value?.level}}</td>

Comments

-1

try something like this :

<div *ngFor="let breed of breeds">

  <div>{{ breed.weight.imperial }}</div>

  <div>{{ breed.weight.metric }}</div>

</div>

1 Comment

while it works for this case, I need something more 'dynamic' to just iterate over keys and values as there are more objects inside

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.