Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

RxJS 6 get a filtered list of array of Observable

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.

like image 376
Johan Rin Avatar asked Jun 02 '18 17:06

Johan Rin


2 Answers

I 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)
      )
    )
  }
like image 164
hamilton.lima Avatar answered Oct 13 '22 02:10

hamilton.lima


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),
like image 25
martin Avatar answered Oct 13 '22 03:10

martin