Angular: Cannot find a differ supporting object '[object Object]'
Asked Answered
O

8

71

Im following this tutorial. On the way to get list of users from api.github Im getting error:

Cannot find a differ supporting object '[object Object]'

I think its related to

 <ul>
 <li *ngFor = "#user of users">
 {{user | json}}
 </li>
 </ul>

In my code because before it there was no any error, and im unsure if data come from get request, just clicking didnt give any error, here is my code so far

@Component({
selector: 'router',
pipes : [],

template: `
<div>
<form [ngFormModel] = "searchform">
      <input type = 'text' [ngFormControl]= 'input1'/>
</form>
     <button (click) = "getusers()">Submit</button>
</div>
<div>
<ul>
    <li *ngFor = "#user of users">
    {{user | json}}
    </li>
</ul>
</div>
<router-outlet></router-outlet>
`,
directives: [FORM_DIRECTIVES]
})
export class router {
searchform: ControlGroup;
users: Array<Object>[];
input1: AbstractControl;

constructor(public http: Http, fb: FormBuilder) {
    this.searchform = fb.group({
        'input1': ['']
    })
    this.input1 = this.searchform.controls['input1']
}
getusers() {
    this.http.get(`https://api.github.com/
search/users?q=${this.input1.value}`)
        .map(response => response.json())
        .subscribe(
        data => this.users = data,
        error => console.log(error)
        )
}
}
bootstrap(router, [HTTP_PROVIDERS])
Overweening answered 26/2, 2016 at 19:42 Comment(0)
M
57

I think that the object you received in your response payload isn't an array. Perhaps the array you want to iterate is contained into an attribute. You should check the structure of the received data...

You could try something like that:

getusers() {
  this.http.get(`https://api.github.com/search/users?q=${this.input1.value}`)
    .map(response => response.json().items) // <------
    .subscribe(
      data => this.users = data,
      error => console.log(error)
    );
}

Edit

Following the Github doc (developer.github.com/v3/search/#search-users), the format of the response is:

{
  "total_count": 12,
  "incomplete_results": false,
  "items": [
    {
      "login": "mojombo",
      "id": 1,
      (...)
      "type": "User",
      "score": 105.47857
    }
  ]
}

So the list of users is contained into the items field and you should use this:

getusers() {
  this.http.get(`https://api.github.com/search/users?q=${this.input1.value}`)
    .map(response => response.json().items) // <------
    .subscribe(
      data => this.users = data,
      error => console.log(error)
    );
}
Malayan answered 26/2, 2016 at 19:57 Comment(3)
by doing this error didnt show also no user displayed, console.log is emptyOverweening
You shoud use items. See this doc: developer.github.com/v3/search/#search-users for the format of the response payload. This corresponds to the array of users in the response payload... I updated my answerMalayan
For me the error happened because I had a template variable (e.g. <div #users>) with the same name as the variable I was setting with data for the ngFor. So Angular was overriding my variable with the template variable. facepalmAcronym
R
15

Missing square brackets around input property may cause this error. For example:

Component Foo {
    @Input()
    bars: BarType[];
}

Correct:

<app-foo [bars]="smth"></app-foo>

Incorrect (triggering error):

<app-foo bars="smth"></app-foo>

Radiant answered 5/11, 2018 at 19:23 Comment(2)
I lost an hour because of this! - Thanks!Blamed
A special case: Running some karma tests for my application, I got this error when setting styles in the template directly on primeng components. Putting the style in a <span> around the component solved it. When running the application itself, the error did not show at all.Eger
L
14

I received this error in my code because I'd not run JSON.parse(result).

So my result was a string instead of an array of objects.

i.e. I got:

"[{},{}]" 

instead of:

[{},{}]

import { Storage } from '@ionic/storage';
...
private static readonly SERVER = 'server';
...
getStorage(): Promise {
  return this.storage.get(LoginService.SERVER);
}
...
this.getStorage()
  .then((value) => {
     let servers: Server[] = JSON.parse(value) as Server[];
                   }
  );
Lemming answered 11/8, 2017 at 11:23 Comment(0)
S
7

Something that has caught me out more than once is having another variable on the page with the same name.

E.g. in the example below the data for the NgFor is in the variable requests. But there is also a variable called #requests used for the if-else

<ng-template #requests>
  <div class="pending-requests">
    <div class="request-list" *ngFor="let request of requests">
      <span>{{ request.clientName }}</span>
    </div>
  </div>
</ng-template>
Staphyloplasty answered 19/5, 2019 at 5:48 Comment(2)
That would seem to be a fairly common reason for this error, it just bit me. Thanks!Crestfallen
You just saved me what might have been hours, thank you!Overripe
D
7

This ridiculous error message merely means there's a binding to an array that doesn't exist.

<option
  *ngFor="let option of setting.options"
  [value]="option"
  >{{ option }}
</option>

In the example above the value of setting.options is undefined. To fix, press F12 and open developer window. When the the get request returns the data look for the values to contain data.

If data exists, then make sure the binding name is correct

//was the property name correct? 
setting.properNamedOptions

If the data exists, is it an Array?

If the data doesn't exist then fix it on the backend.

Dissimilation answered 8/4, 2020 at 15:55 Comment(1)
Solved my issue not being able to loop through Wordpress tag id data, which was in the form of[...{"tags": [2,3,4],}...]Silvas
P
1

If this is an Observable being return in the HTML simply add the async pipe

    observable | async
Paresis answered 20/4, 2020 at 0:27 Comment(0)
N
0

Explanation: You can *ngFor on the arrays. You have your users declared as the array. But, the response from the Get returns you an object. You cannot ngFor on the object. You should have an array for that. You can explicitly cast the object to array and that will solve the issue. data to [data]

Solution

getusers() {
    this.http.get(`https://api.github.com/
search/users?q=${this.input1.value}`)
        .map(response => response.json())
        .subscribe(
        data => this.users = [data], //Cast your object to array. that will do it.
        error => console.log(error)
        )
Neuroblast answered 19/3, 2020 at 22:59 Comment(0)
D
0

If you don't have an array but you are trying to use your observable like an array even though it's a stream of objects, this won't work natively. I show how to fix this below.

If you are trying to use an observable whose source is of type BehaviorSubject, change it to ReplaySubject then in your component subscribe to it like this:

Component

this.messages$ = this.chatService.messages$.pipe(scan((acc, val) => [...acc, val], []));

Html

<div class="message-list" *ngFor="let item of messages$ | async">
Depicture answered 5/5, 2020 at 15:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.