In my ThreadService class, I have a function getThreads()
that return me a Observable<Thread[]>
with all my threads.
Now, I would like to have another version of my function with my threads filtered by a selected theme : function getSelectedThemeThreads(theme: Theme)
.
I tried with the operators map
and filter
but I have the following error message Property 'theme' does not exist on type 'Thread[]
.
Below the code I am working on :
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Thread } from '../models/thread.model';
import { Theme } from '../models/theme.model';
@Injectable({
providedIn: 'root'
})
export class ThreadService {
private threadsUrl = 'api/threads';
constructor(private http: HttpClient) { }
getThreads(): Observable<Thread[]> {
return this.http.get<Thread[]>(this.threadsUrl);
}
getSelectedThemeThreads(): Observable<Thread[]> {
return this.http.get<Thread[]>(this.threadsUrl).pipe(
map(threads => threads),
filter(thread => thread.theme.id === theme.id)
);
}
Thanks in advance for your help.
In my ThreadService class, I have a function getThreads()
that return me a Observable<Thread[]>
with all my threads.
Now, I would like to have another version of my function with my threads filtered by a selected theme : function getSelectedThemeThreads(theme: Theme)
.
I tried with the operators map
and filter
but I have the following error message Property 'theme' does not exist on type 'Thread[]
.
Below the code I am working on :
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, of } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { Thread } from '../models/thread.model';
import { Theme } from '../models/theme.model';
@Injectable({
providedIn: 'root'
})
export class ThreadService {
private threadsUrl = 'api/threads';
constructor(private http: HttpClient) { }
getThreads(): Observable<Thread[]> {
return this.http.get<Thread[]>(this.threadsUrl);
}
getSelectedThemeThreads(): Observable<Thread[]> {
return this.http.get<Thread[]>(this.threadsUrl).pipe(
map(threads => threads),
filter(thread => thread.theme.id === theme.id)
);
}
Thanks in advance for your help.
Share Improve this question edited Dec 10, 2018 at 11:48 Johan Rin asked Jun 2, 2018 at 17:19 Johan RinJohan Rin 1,9503 gold badges22 silver badges42 bronze badges 2- I think threads is an array you should do like map(threads => threads.filter) filter in this case is standard js – Whisher Commented Jun 2, 2018 at 17:24
- filter can be a starndar js (then use inside map) or Rxjs learnrxjs.io/operators/filtering/filter.html. But..What is theme.id in thread.theme.id=== theme.id ? – Eliseo Commented Jun 3, 2018 at 14:03
5 Answers
Reset to default 10I made an example of this StackBlitz / angular6-filter-result
The main idea is to filter in the map()
as the filter will get an array of objects.
getSelectedThemeThreads(theme: string): Observable<Flower[]> {
return this.http.get<Flower[]>(this.threadsUrl).pipe(
map(result =>
result.filter(one => one.theme === theme)
)
)
}
You were almost there. Using this map(threads => threads)
does nothing but you probably wanted to use this instead:
mergeMap(threads => threads) // will turn Observable<Thread[]> into Observable<Thread>
concatMap
or switchMap
will work as well. The mergeMap
operator will iterate the array and emit each item separately so then you can use filter()
as you're doing already.
You could of course use also this:
map(threads => threads.find(thread => thread.theme.id === theme.id)),
filter(thread => thread !== undefined),
Try by using the following code.
getSelectedThemeThreads(theme): Observable<Thread[]> {
return this.http.get<Thread[]>(this.threadsUrl)
.map(res => res)
.filter(thread => thread.theme.id == theme.id);
}
Just change map(threads => threads)
to mergeAll()
I think you are looking for grupoby
operator:
getSelectedThemeThreads(): Observable<Thread[]> {
return this.http.get<Thread[]>(this.threadsUrl).pipe(
groupby(thread => thread.id),
mergeAll(group$ => group$.pipe(
reduce((acc, cur) =>[...acc, cur], [])
)
);
}
Let me know how this code works for you. In any case, if you need to play with it, a while ago a came with this example, I hope it helps you to clarify.