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

21

93

I looked at similar questions, but none of them helped me. I am going to receive an object like the following:

[
  {
    "id": 1,
    "name": "Safa",
    "email": "[email protected]",
    "purpose": "thesis",
    "programme": "Software Engineering",
    "year": 2016,
    "language": "Estonian",
    "comments": "In need of correcting a dangling participle.",
    "status": "RECEIVED"
  },
  {
    "id": 2,
    "name": "Safa",
    "email": "[email protected]",
    "purpose": "thesis",
    "programme": "Software Engineering",
    "year": 2016,
    "language": "Estonian",
    "comments": "In need of correcting a dangling participle.",
    "status": "RECEIVED"
  },
  {
    "id": 3,
    "name": "Salman",
    "email": "[email protected]",
    "purpose": "thesis",
    "programme": "Software Engineering",
    "year": 2016,
    "language": "Estonian",
    "comments": "In need of correcting a dangling participle.",
    "status": "RECEIVED"
  }
]

and here is my http service to receive it:

getRequest(){
        return this._http.get("http://consultationwebserver.herokuapp.com/requests").map(res => res.json());
    }

and finally, in the i called the service in this way:

requests;
    constructor(private _http:requestService){}
    ngOnInit(){
        this.requests=this._http.getRequest().subscribe(res=>this.requests=res);
    }

Unfortunately, when the page loads it complains with:

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

So, what is going wrong with this code?

Felten answered 2/10, 2016 at 16:56 Comment(1)
Please add your template code where you are using this object.Krum
D
46

There you don't need to use this.requests= when you are making get call(then requests will have observable subscription). You will get a response in observable success so setting requests value in success make sense(which you are already doing).

this._http.getRequest().subscribe(res=>this.requests=res);

If it still shows an error related to type, add any/RelevantModel type on subscribe parameter object.

this._http.getRequest().subscribe(
  (res: any[]) => this.requests =res
);

Basically, *ngFor works for only iterable items like arrays. If you assign this.requests to have an object value, and you're trying to use *ngfor it will return this error.

For example, when you declare array like this.myArray = {} this problem will occur. It should be this.myArray = [].

Diacritic answered 2/10, 2016 at 16:58 Comment(3)
That is not the solution for above mentioned error(Cannot find a differ supporting object '[object Object]' of type 'object'.) He has to use dataType like for ex: requests: any=[] Even i faced the same and I fixed by adding dataTypeHesperides
Agreed @Hesperides the error is thrown only when it can't render the object's membersBeffrey
basically NgFor works for only iterable items like arrays. if you declare dictonary and trying to use *ngfor it will these type of errors. for example when you declare array like this.myArray = {}.. problem will occur.. it should be this.myArray = []. than problem will solve.Brakesman
P
19

Remove this.requests from

ngOnInit(){
  this.requests=this._http.getRequest().subscribe(res=>this.requests=res);
}

to

ngOnInit(){
  this._http.getRequest().subscribe(res=>this.requests=res);
}

this._http.getRequest() returns a subscription, not the response value. The response value is assigned by the callback passed to subscribe(...)

Procurable answered 2/10, 2016 at 16:58 Comment(2)
Any idea how to show the response in the console?When I do console.log(this.requests) I get a subscriber objectKinsfolk
this._http.getRequest().subscribe(res=>{ this.requests=res; console.log(this.requests);});Arguello
N
12

You can declare the books (on line 2) as an array:

title: any = 'List of books are represted in the bookstore';
books: any = []; 
constructor(private service:  AppService){
}

ngOnInit(){
  this.getBookDetails();
}

getBookDetails() {
    this.service.getBooks().subscribe(books => {
        this.books = books.json();
        console.log(this.books);
    });
}
Nicholasnichole answered 24/8, 2017 at 9:9 Comment(3)
There is no books mentioned in the question.Arguello
must say, that helped since i init'ed my array as products = {} and should have done products:any = [], since the *ngFor 1st ran on an empty object which he cantTena
@Tena same with me.. thanks for pointing it out.. it solved my issue as well.. :)Ghirlandaio
P
9

My solution is create a Pipe for return the values array or propierties object

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

@Pipe({
  name: 'valueArray',
})
export class ValueArrayPipe implements PipeTransform {

  // El parametro object representa, los valores de las propiedades o indice
  transform(objects : any = []) {
    return Object.values(objects);
  }
}

The template Implement

<button ion-item *ngFor="let element of element_list | valueArray" >
    {{ element.any_property }}
</button> 
Packer answered 17/1, 2018 at 9:40 Comment(2)
This was the solution that worked for me with just one workaround... I had to describe the return parameter of the transform function, like this js transform(objects : any = []): ChildProcess[] { ... Is there a more logic explanation of this issue?Zebu
Thanks, I changed the transform syntax a bit for Angular 12 strict: stefvanlooveren.me/errors/…Querulous
P
7

I had the same error because I have mapped the HTTP response like this:

this.http.get(url).map(res => res.json);

Note how I accidentally called .json like a variable and not like a method.

Changing it to:

this.http.get(url).map(res => res.json());

did the trick.

Phoney answered 18/12, 2016 at 19:25 Comment(1)
My problem is I did not wrap my response from the server with 'data', as recommended in the angular 2 hero tutorialAttempt
T
7

In your JSOn file, please make below change.

 {
    "data":
    [
      {
        "id": 1,
        "name": "Safa",
        "email": "[email protected]",
        "purpose": "thesis",
        "programme": "Software Engineering",
        "year": 2016,
        "language": "Estonian",
        "comments": "In need of correcting a dangling participle.",
        "status": "RECEIVED"
      },
      {
        "id": 2,
        "name": "Safa",
        "email": "[email protected]",
        "purpose": "thesis",
        "programme": "Software Engineering",
        "year": 2016,
        "language": "Estonian",
        "comments": "In need of correcting a dangling participle.",
        "status": "RECEIVED"
      },
      {
        "id": 3,
        "name": "Salman",
        "email": "[email protected]",
        "purpose": "thesis",
        "programme": "Software Engineering",
        "year": 2016,
        "language": "Estonian",
        "comments": "In need of correcting a dangling participle.",
        "status": "RECEIVED"
      }
    ]
    }

And after that:

 this.http.get(url).map(res:Response) => res.json().data);

The data is actually the name of tge collection of json file. Please try the code above, I am sure it will work.

Titty answered 10/11, 2017 at 15:14 Comment(0)
F
4

To iterate over an object which has a json format like below

{
  "mango": { "color": "orange", "taste": "sweet" }
  "lemon": { "color": "yellow", "taste": "sour" }
}
  1. Assign it to a variable

    let rawData = { "mang":{...}, "lemon": {...} }

  2. Create a empty array(s) for holding the values(or keys)

    let dataValues = []; //For values

    let dataKeys = []; //For keys

  3. Loop over the keys and add the values(and keys) to variables

    for(let key in rawData) { //Pay attention to the 'in' dataValues.push(rawData[key]); dataKeys.push(key); }

  4. Now you have an array of keys and values which you can use in *ngFor or a for loop

    for(let d of dataValues) { console.log("Data Values",d); }

    <tr *ngFor='let data of dataValues'> ..... </tr>

Flown answered 2/10, 2018 at 15:44 Comment(0)
P
4

For anyone else with this issue that arrives here via Google, please check that the host element of the *ngFor directive is accurate. By this, I mean that I encountered this error and spent a long time researching fixes before realizing that I had put the *ngFor on an ng-template element instead of on my component I wanted to repeat.

Incorrect

<ng-template *ngFor=let group of groups$ | async" ...>
  <my-component [prop1]="group.key" ... </my-component>
<\ng-template>

Correct

<my-component *ngFor=let group of groups$ | async" [prop1]="group.key" ... </my-component>

I know this is an obvious mistake in hindsight, but I hope an answer here will save someone the headache I now have.

Pearliepearline answered 6/9, 2019 at 19:49 Comment(0)
S
3

i have the same problem. this is how i fixed the problem. first when the error is occurred, my array data is coming form DB like this --,

{brands: Array(5), _id: "5ae9455f7f7af749cb2d3740"} 

make sure that your data is an ARRAY, not an OBJECT that carries an array. only array look like this --,

(5) [{…}, {…}, {…}, {…}, {…}]

it solved my problem.

Syncarpous answered 10/5, 2018 at 7:6 Comment(0)
E
3

You should use async pipe. Doc: https://angular.io/api/common/AsyncPipe

For example:

<li *ngFor="let a of authorizationTypes | async"[value]="a.id">
     {{ a.name }}
</li>
Errolerroll answered 19/2, 2019 at 23:33 Comment(1)
This approach solved my problem. It was before I read this answer, but It worth to let others know that your approach works. Thanks.Benton
E
2

i have faced same problem

my initial json

{"items":

         [
           {"id":1,
            "Name":"test4"
           },
           {"id":2,
            "Name":"test1"
           }
         ]
}

i have changed my json inside []

[{"items":

         [
           {"id":1,
            "Name":"test4"
           },
           {"id":2,
            "Name":"test1"
           }
         ]
}]
Edmondo answered 9/2, 2018 at 10:42 Comment(0)
G
1

this.requests=res here you are trying to assign following response to object,

{"headers":{"normalizedNames":{},"lazyUpdate":null},"status":200,"statusText":"OK",
"url":"xyz","ok":true,"type":4,"body":[{}]}

Since, object format is different then response format you have to assign res.body part from your response to get required contents.

Guillermoguilloche answered 16/7, 2018 at 14:29 Comment(0)
U
1
<ul>
<li *ngFor = "let Data of allDataFromAws  | async">
  <pre> {{ Data | json}}</pre>
</li>
</ul>

use async to convert allDataFromAws into Array Object....

Unbending answered 24/10, 2018 at 10:54 Comment(0)
L
1

Just declare the var as an array in which you holding the data , it worked for me.

listingdata:Array<any> = [];
this.listingdata = data.results.rows;

and loop the listingdata on html page

Lanie answered 21/5, 2019 at 6:33 Comment(0)
L
1

Here is the solution.

When you are receiving array from your database. and you are storing array data inside a variable but the variable defined as object. This time you will get the error.

I am receiving array from database and I'm stroing that array inside a variable 'bannersliders'. 'bannersliders' type is now 'any' but if you write 'bannersliders' is an object. Like bannersliders:any={}. So this time you are storing array data inside object type variable. So you find that error.

So you have to write variable like 'bannersliders:any;' or 'bannersliders:any=[]'.

Here I am giving an example.

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
bannersliders:any;
  getallbanner(){
    this.bannerService.getallbanner().subscribe(data=>{
      this.bannersliders =data;
   })
  }
Lani answered 21/8, 2020 at 9:17 Comment(0)
F
0

In you use spring boot with Angular ; make sure that whether you create default

Frodeen answered 5/11, 2018 at 7:24 Comment(1)
make sure that you should use default constructorFrodeen
Q
0

*********** PARSE THE RESULT TO JSON OBJECT: JSON.prase(result.arrayOfObjects) ***********

I came to this page after I faced this issue. So, my issue was that the server is sending array of objects in the form of string. It is something like this:

when I printed result on console after getting from server it is string:

'arrayOfObject': '[
                  {'id': '123', 'designation': 'developer'},
                  {'id': '422', 'designation': 'lead'}
               ]'

So, I have to convert this string to JSON after getting it from server. Use method for parsing the result string that you receive from server:

JSON.parse(result.arrayOfObjects)
Quoth answered 16/1, 2020 at 20:3 Comment(1)
The above one is a scenario where the result you are getting is in the string data type. So, check the data type and if it is string parse it.Quoth
B
0
Store that objects into Array  and then iterate the Array
export class AppComponent {

 public obj: object =null;
 public myArr=[];

  constructor(){

    this.obj = {
      jon : {username: 'Jon', genrePref: 'rock'},
      lucy : {username: 'Lucy', genrePref: 'pop'},
      mike : {username: 'Mike', genrePref: 'rock'},
      luke : {username: 'Luke', genrePref: 'house'},
      james : {username: 'James', genrePref: 'house'},
      dave : {username: 'Dave', genrePref: 'bass'},
      sarah : {username: 'Sarah', genrePref: 'country'},
      natalie : {username: 'Natalie', genrePref: 'bass'}
  }
  }
  ngOnInit(){
    this.populateCode();
  }

  populateCode(){
    for( let i in this.obj) {   //Pay attention to the 'in'
    console.log(this.obj[i]);
    this.myArr.push(this.obj[i]);
  }
  }
 }



<div *ngFor="let item of myArr ">
    {{item.username}}
    {{item.genrePref}}
  </div>
Bannock answered 24/9, 2020 at 10:18 Comment(0)
T
0

I don't know if someone would get the same thing as me, and I have no idee why this happens (maybe is a bug?), but I actually had this error because only because we were trying to create a ComponentPortal for an angular overlay like this:

const smartfillPortal = new ComponentPortal(
  SmartFillModalComponent,
  this.viewContainerRef,
  {
    get: () => this.smartfillOverlayRef,
  }
);

changing it to

const smartfillPortal = new ComponentPortal(SmartFillModalComponent);

fixed it for some reason (I am guessing I am also missing some info about overlays?).

The weird thing is that even something like this in the overlay code:

<div class="flex" *ngFor="let i of [1,2,3]; let i = index">
  <span>hi there</span>
</div>

would result in

Error: Cannot find a differ supporting object '1,2,3' of type 'object'. NgFor only supports binding to Iterables such as Arrays.

enter image description here

Thalamus answered 5/5, 2022 at 11:49 Comment(0)
K
0

You can also change how you access the property. I faced this issue and instead of accessing :

this.someService.details

I've used :

this.someService['details'];

This fixed this error for me.

Kuhlman answered 1/6, 2023 at 12:50 Comment(0)
U
-1

For me the error was resolved when I added the index to *ngFor.

<tr *ngFor = "let element of element_list; let i=index">
             <td>{{element.id}}</td>
             <td>{{element.status}}</td>
             <td>{{element.name}}</td>
 </tr>
Unveil answered 18/1, 2022 at 6:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.