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

Viewed 4651

I'm creating an Angular app which shows list of projects and list of users from postgresql database, but I'm having issues with showing list of users in html. The problem is that Angular is considering my array as an object no matter what I do. The same code worked for projects but didn't work for users.

This is my service:

    import { environment } from "../../../environments/environment";
    import { Observable } from 'rxjs';
    import { Projet } from '../modele/projet.model';
    import { Test } from '../modele/test.model';
    import { HttpParams,HttpClient } from "@angular/common/http";
    import { Injectable } from "@angular/core";
    import { map } from 'rxjs/operators';
    import { User } from '../modele/user.model';
    import { Financement } from '../modele/financement.model';
        
    @Injectable()
    export class WebService {
            
        constructor(private httpClient: HttpClient) { }
            
        serverUrl: string = "http://localhost:8080/"
              
        get(url: string): Observable<any> {
            return this.httpClient.get(this.serverUrl + url);
        }
    }

The component :

    import { Component, OnInit } from '@angular/core';
    import { User } from '../../shared/modele/user.model';
    import { Router } from '@angular/router';
    import { WebService } from '../../shared/sevices/web.service';
    import { FormGroup, FormBuilder, FormControl, Validators, Form } from '@angular/forms';
    
    @Component({
      selector: 'app-show-users',
      templateUrl: './show-users.component.html',
      styleUrls: ['./show-users.component.scss']
    })

    export class ShowUsersComponent implements OnInit {
    
        ngOnInit(): void {
          this.getData();
        }
        usersList: Array<User>
        user: User 
        myForm: FormGroup;
      
        constructor(private webService: WebService, private formBuilder: FormBuilder,private router: Router) { }
      
        getData(): void {
          this.webService.get("showUsers").subscribe(res => {
            let response = JSON.parse(JSON.stringify(res))
            this.usersList = response.data
      
          })
        }
      }

The html :

        <tr *ngFor="let user of usersList">
            <td>{{user.name}}</td>            
            <td>{{user.username}}</td>
            <td>{{user.email}}</td>
        </tr>

This is the server response : server response

NB: the EXACT same code worked for the object PROJECT

3 Answers

You need to make sure that the variable you pass into *ngFor is an array. You can make sure of this with Array.from(v) and can also strip any keys of an Object that might be sent from the serverside with Object.values(v):

this.webService.get("showUsers").subscribe(res => {
  this.usersList = Array.from(Object.values(res.data.body.data));
})

You don't need this code:

let response = JSON.parse(JSON.stringify(res))
this.usersList = response.data

simply use:

this.userlist = res

Youe complete method:

this.webService.get("showUsers").subscribe(res => {
  this.userlist = res
});

In my case, I have a simple approach, but I spent a lot of time. You could try this:

datas: any;

this.token = JSON.parse(window.localStorage.getItem('token'));

this.authService.getData(this.token.id).subscribe(data => { 
    this.datas = data;  
})

In the HTML template just use this.datas.id, this.datas.username instead of an *ngFor

Related