Using the Hero example from angular.io:
/* GET heroes whose name contains search term */
searchHeroes(term: string): Observable<Hero[]> {
if (!term.trim()) {
// if not search term, return empty hero array.
return of([]);
}
return this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`).pipe(
tap(x => x.length ?
this.log(`found heroes matching "${term}"`) :
this.log(`no heroes matching "${term}"`)),
catchError(this.handleError<Hero[]>('searchHeroes', []))
);
}
How can I change this so that any searchable attribute of a Hero is captured with this search? For example, suppose address is a searchable attribute, so that:
this.http.get<Hero[]>(`${this.heroesUrl}/?address=${term}`)
works fine.
I tried this modification:
/* GET heroes whose name contains search term */
searchHeroes(term: string): Observable<Hero[]> {
if (!term.trim()) {
// if not search term, return empty hero array.
return of([]);
}
var names = this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`).pipe(
tap(x => x.length ?
this.log(`found heroes matching "${term}"`) :
this.log(`no heroes matching "${term}"`)),
catchError(this.handleError<Hero[]>('searchHeroes', []))
);
var addresses = this.http.get<Hero[]>(`${this.heroesUrl}/?address=${term}`).pipe(
tap(x => x.length ?
this.log(`found heroes matching "${term}"`) :
this.log(`no heroes matching "${term}"`)),
catchError(this.handleError<Hero[]>('searchHeroes', []))
);
return names addresses;
}
But this doesn't work at all because the result of the http GET is an Observable, not a string. However, the type or kind of result in each case is the same thing (a Hero), so I ought to be able to implement something like this, right?
Before you ask, I know I really ought to modify the API this function is calling to do something like this:
this.http.get<Hero[]>(`${this.heroesUrl}/?searchable=${term}`)
where searchable is any searchable Hero attribute, but I can't modify API at this time (and I will in the future). For now, can I implement this hack? How can I concatenate the result of Observables?
CodePudding user response:
Use the forkJoin
operator:
searchHeroes(term: string): Observable<Hero[]> {
...
return forkJoin({
names: this.http.get<Hero[]>(`${this.heroesUrl}/?name=${term}`),
addresses: this.http.get<Hero[]>(`${this.heroesUrl}/?address=${term}`)
}).pipe(map(({ names, addresses}) => names.concat(addresses));
}