Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ngFor inside ngFor

I have Angular + Firebase app. In one of my components i get elements from Firebase DB and binding them into template with *ngFor:

<div *ngFor="let comment of (comments | async)>
   <div>{{ comment.text }}</div>
</div>

But every comment also have answers list: firebase db

How can i bind answers inside my loop, for example, something like this:

<div *ngFor="let comment of (comments | async)>
   <div>{{ comment.text }}</div>

   <div *ngFor="let answer of comment.answers">
     {{ answer.text }}
   </div
</div>

This structure does not work and return error:

Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

like image 269
Vladimir Humeniuk Avatar asked Apr 19 '18 12:04

Vladimir Humeniuk


People also ask

Can I use ngFor inside ngFor?

You must convert it into an array, before displaying it in your *ngFor loop. If you want to keep the key, you can merge it into the object in the map call as well.

Can we use two ngFor in angular?

You can't use multiple *ngFor s in the same element as those are structural directives and angular handles them in a specific way (basically for each structural directive it creates an ng-template element which then holds the directive itself, you can read more about it here: https://angular.io/guide/structural- ...

Why * is used in ngFor?

In *ngFor the * is a shorthand for using the new angular template syntax with a template tag, this is also called structural Directive.It is helpful to know that * is just a shorthand to explicitly defining the data bindings on a template tag.

What is * in ngFor angular?

*ngFor is a predefined directive in Angular. It accepts an array to iterate data over atemplate to replicate the template with different data. It's the same as the forEach() method in JavaScript, which also iterates over an array.


1 Answers

The answers property is an object. You must convert it into an array, before displaying it in your *ngFor loop.

component.html

<div *ngFor="let comment of (comments | async)>
   <div>{{ comment.text }}</div>

   <div *ngFor="let answer of toArray(comment.answers)">
     {{ answer.text }}
   </div
</div>

component.ts

export class Component {
  toArray(answers: object) {
    return Object.keys(answers).map(key => answers[key])
  }
}

If you want to keep the key, you can merge it into the object in the map call as well.

export class Component {
  toArray(answers: object) {
    return Object.keys(answers).map(key => ({
      key,
      ...answers[key]
    }))
  }
}
like image 183
Tomasz Kula Avatar answered Oct 13 '22 01:10

Tomasz Kula