Reputation: 4313
I am building an app with Angular 2
. I have a service, and I am trying to filter the data before getting it from the service. I want a function where I can just ask one project element instead of the whole array.
This is the code I tried, but this approach doesn't work:
getProject(id: number): Observable<Project> {
return this.http.get(this.url).map(this.extractData).filter(project => (<Project>project).id == id).catch(this.handleError2);
// return this.getProjects().filter(project => project.id === id);
//return this.http.get(this.url).toPromise().then(x => x.json().data.filter(project => project.id === id)[0]).catch(this.handleError);
}
private extractData(res: Response) {
let body = res.json();
return body.data || { };
}
private handleError2 (error: any) {
// In a real world app, we might use a remote logging infrastructure
// We'd also dig deeper into the error to get a better message
let errMsg = (error.message) ? error.message :
error.status ? `${error.status} - ${error.statusText}` : 'Server error';
console.error(errMsg); // log to console instead
return Observable.throw(errMsg);
}
Upvotes: 2
Views: 3602
Reputation: 10474
To me, it looks like you're mixing sync and async code, and return doesn't work like that. You can return an object (function) who's properties change later (aka a Promise)
I doubt that http.get()
provides an array for you to map
.toPromise()
seems like a hack, but you should return a Promise chain
return this.http.get(this.url).then(data => data.map(this.extractData).filter(project => (<Project>project).id == id).catch(this.handleError2));
If this.http.get()
does not return a Promise, but takes a callback, you can construct one:
return new Promise (resolve => this.http.get(this.url, resolve)).then(data => data.map(this.extractData).filter(project => (<Project>project).id == id).catch(this.handleError2));
And whatever is calling getProject()
can chain with getProject().then()
Upvotes: 1
Reputation: 337
If this part of code works :
getProjects() {
return this.http.get(this.url).map(this.extractData).catch(this.handleError2);
}
Then you can call a single project with :
getProject(id: number) {
return this.getProjects()
.then(projects => projects.filter(project => (<Project>project).id == id);
}
Upvotes: 0
Reputation: 13558
Its better to filter data in component from where you have called the service.
So your service is like :
getProject(id: number): Observable<Project> {
return this.http.get(this.url).map(this.extractData);
}
private extractData(res: Response) {
let body = res.json();
return body.data || []; // return value must be array to use filter function in component
}
in your component you can do as below :
service.getProject(projectId).subscribe((res) => {
let filtered = [];
if(res.length){
filtered = res.filter((item) => {
return item.id === projectId;
});
}
});
Upvotes: 1