I'm trying to load an array of objects from a JSON and display them in my template with *ngFor in my angular2 app. I'm getting this error Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays.
.
I've found quite a bit of documentation on this particular error and a fix, but I'm having trouble understanding/translating it into a working fix. From what I understand the *ngFor will only render arrays of data and my home.component is trying to render an object of arrays.
The fix I've read is to write a pipe like this:
@Pipe({ name: 'values', pure: false })
export class ValuesPipe implements PipeTransform {
transform(value: any, args: any[] = null): any {
return Object.keys(value).map(key => value[key]);
}
}
I've tried this but then I'm getting an error that says compiler.umd.js?9df7:14126Uncaught Error: Unexpected value 'HomeComponent' declared by the module 'AppModule'
I've built the pipe directly into my home component so I'm unsure why this is a problem.
Here is my code.
home.component.js
import { Component, OnInit, Pipe, PipeTransform } from '@angular/core';
import { Project } from './project';
import { ProjectService } from './project.service';
@Component({
selector: 'home',
templateUrl: './home.html',
styleUrls: ['./home.scss'],
providers: [ProjectService]
})
@Pipe({ name: 'values', pure: false })
export class ValuesPipe implements PipeTransform {
transform(value: any, args: any[] = null): any {
return Object.keys(value).map(key => value[key]);
}
}
export class HomeComponent implements OnInit {
errorMessage: string;
projects: Project[];
selectedProject: Project;
mode = 'Observable';
constructor(private projectService: ProjectService) { }
ngOnInit() { this.getProjects(); }
getProjects() {
this.projectService.getProjects()
.subscribe(
projects => this.projects = projects,
error => this.errorMessage = <any>error);
}
onSelect(project: Project): void {
this.selectedProject = project;
}
}
projects.service.js
import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Project } from './project';
import { Observable } from 'rxjs/Observable';
@Injectable()
export class ProjectService {
private projectsUrl = 'data/project.json'; // URL to web API
constructor(private http: Http) { }
getProjects(): Observable<Project[]> {
return this.http.get(this.projectsUrl)
.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, we 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);
}
}
project.json
{
"project": [{
"title": "The Upper Crust",
"id": "upper-crust",
"year": "2016",
"category": ["Design", "Web Design"],
"thumbnail": "thumbnails/upper-crust.jpg"
}, (...)
}
Sorry if the answer is already out there I've spent a few hours last night and this morning trying to solve this issue and can't seem to figure it out. I appreciate your help in advance, I'm new to development and am at a loss with much of this stuff.
data
in your json, so your extractData method returns an empty object. This kind of error is very easy to find by just using your debugger. – JB Nizet Oct 27 '16 at 16:59