Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to loop over object properties with ngFor in Angular

this is post is about an interesting problem I found at work.

If you don’t know it yet. I’m talking about Angular 2+

The problem

So you want to display the markup for a list, the values for this list come from the back end and for some reason instead of a good old array of objects you receive something like this.

    { 
  "car" : 
    { 
       "color" : "red",
       "model" : "2013"
    },
   "motorcycle": 
    { 
       "color" : "red",
       "model" : "2016"
    },
   "bicycle": 
    { 
       "color" : "red",
       "model" : "2011"
    }
}

Then you try to use *ngFor but a wild error message appears:

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

You might fix it in the back end so you get an array of objects, but ain’t no body got time for that. Don’t you worry child, I’ve got us.

like image 363
Jaime Rios Avatar asked Aug 22 '17 13:08

Jaime Rios


People also ask

How do you loop an object using ngFor?

To iterate object keys using *ngFor in Angular, we can use the keyvalue pipe. to add use the keyvalue with *ngFor . We use it to render entries in objects and maps. And we get the key from the key property and the value from value .

How we can loop over object properties in Angular?

To iterate over object in Angular, we can use the keyvalue pipe. to loop through the entries in myObject by using the keyvalue pipe with *ngFor . Then we get the key's value from item. key and the value's value with item.

Which loop is used to loop through an object properties?

for...in Loop The most straightforward way to loop through an object's properties is by using the for...in statement. This method works in all modern and old browsers including Internet Explorer 6 and higher.


3 Answers

In Angular 6.1 the KeyValuePipe was introduced which allows you to iterate object properties:

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

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

like image 150
danday74 Avatar answered Oct 19 '22 11:10

danday74


I don't know if this is safe, but for these simple cases i don't like the pipe solution, so i usually use:

<div *ngFor="let k of objectKeys(yourObject)">
    {{yourObject[k].color}}
</div>

and in the controller:

objectKeys(obj) {
    return Object.keys(obj);
}

This is a quite frequent case, i don't understand why there isn't a standard implementation for this like in Angular.js 1.x

like image 28
Michele Federici Avatar answered Oct 19 '22 12:10

Michele Federici


A better solution would be to use a pipe such as this one:

import { Pipe, PipeTransform } from '@angular/core';

/**
 * Convert Object to array of keys.
 */
@Pipe({
  name: 'appProperties'
})
export class PropertiesPipe implements PipeTransform {

  transform(value: {}): string[] {

    if (!value) {
      return [];
    }

    return Object.keys(value);
  }
}

Then in your template:

<div *ngFor="let property of response | appProperties">
    <div *ngFor="let item of response[property]">
         {{item.something}}
    </div>
</div>
like image 14
EldarGranulo Avatar answered Oct 19 '22 10:10

EldarGranulo