Maksym Vasylenko
Maksym Vasylenko

Reputation: 27

Can't bind objects from json to angular 2 class

I am new to Angular 2 and I am trying to create service which send get request and gets json. And bind those result from json to array of angular classes. But when there is trouble and something went wrong. I followed documentation on angular.io and did everything like there. Through debugger I found that when i write

return body.data

after that object that returns is undefined.

I got next error:

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

Please help me with this issue.

Json data:

[{"categoryId":1,"categoryName":"cpu"},{"categoryId":2,"categoryName":"gpu"},{"categoryId":3,"categoryName":"motherboard"},{"categoryId":4,"categoryName":"phone"},{"categoryId":5,"categoryName":"hdd"},{"categoryId":6,"categoryName":"ssd"},{"categoryId":7,"categoryName":"ram"},{"categoryId":8,"categoryName":"rom"}]

Entity class:

export class Category {
  constructor(public categoryId: number, public categoryName: string) {}
}

Service class:

@Injectable()
export class CategoryService {
  private currentUrl = 'http://localhost:8081/emusicshop/api/categories';

  constructor (private http: Http) {}

  getCategories(): Observable<Category[]> {
    return this.http.get(this.currentUrl)
      .map(this.extractData)
      .catch(this.handleError);
  }

  private extractData(res: Response) {
    let body = res.json();
    return body.data || { };
  }
  private handleError (error: Response | any) {
    // In a real world app, you might use a remote logging infrastructure
    let errMsg: string;
    if (error instanceof Response) {
      const body = error.json() || '';
      const err = body.error || JSON.stringify(body);
      errMsg = `${error.status} - ${error.statusText || ''} ${err}`;
    } else {
      errMsg = error.message ? error.message : error.toString();
    }
    console.error(errMsg);
    return Observable.throw(errMsg);
  }
}

Component:

Component
export class CategoryComponent implements OnInit {

  allCategories: Category[];

  constructor(private service: CategoryService) { }

  getCategories(): void {
    this.service.getCategories().subscribe(
      categories => this.allCategories = categories);
  }

  ngOnInit() {
    this.getCategories();
  }

}

HTML file:

<ul>
  <li *ngFor="let categ of allCategories">
    Id : {{categ.id}}
    Name : {{categ.name}}
  </li>
</ul>

Upvotes: 0

Views: 916

Answers (1)

eko
eko

Reputation: 40647

Your response object does not have a data field. It should be more like this:

private extractData(res: Response) {
    let body = res.json();
    return body || []; //<-- return an empty array instead of an object so *ngFor won't complain about iteration
}

And try the safe navigation operator on your template ?

<ul>
  <li *ngFor="let categ of allCategories">
    Id : {{categ?.categoryId}}
    Name : {{categ?.categoryName}}
  </li>
</ul>

Upvotes: 1

Related Questions