Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple filter on array of RXJS Observable

I am starting my project with Angular2 and the developers seem to recommend RXJS Observable instead of Promises.

I have achieved to retrieve a list of elements (epics) from the server. But how can I filter the elments by using for example an id?

The following code is an extraction from my app and shows now the final working solution. Let's hope it helps someone.

@Injectable() export class EpicService {    private url = CONFIG.SERVER + '/app/';  // URL to web API    constructor(private http:Http) {}    private extractData(res:Response) {     let body = res.json();     return body;   }    getEpics():Observable<Epic[]> {     return this.http.get(this.url + "getEpics")       .map(this.extractData)       .catch(this.handleError);   }    getEpic(id:string): Observable<Epic> {     return this.getEpics()       .map(epics => epics.filter(epic => epic.id === id)[0]);   } }  export class EpicComponent {    errorMessage:string;   epics:Epic[];   epic:Epic;    constructor(     private requirementService:EpicService) {   }    getEpics() {     this.requirementService.getEpics()       .subscribe(         epics => this.epics = epics,         error => this.errorMessage = <any>error);   }    // actually this should be eventually in another component   getEpic(id:string) {     this.requirementService.getEpic(id)         .subscribe(         epic => this.epic = epic,         error => this.errorMessage = <any>error);   } }  export class Epic {   id: string;   name: string; } 

Thank you in advance for your help.

like image 636
Johannes Avatar asked Jun 23 '16 12:06

Johannes


People also ask

How do you filter Observable data using RxJS operators?

RxJS filter() Filtering Operator The RxJS filter() operator is like the well-known Array Array . prototype. filter() method. This operator takes values from the source Observable, passes them through a predicate function and only emits those values that get TRUE.

How do you map an array to an Observable?

To convert from array to observable you can use Rx. Observable. from(array) . To convert from observable to array, use obs.

What does pipe () do RxJS?

pipelink. pipe() can be called on one or more functions, each of which can take one argument ("UnaryFunction") and uses it to return a value. It returns a function that takes one argument, passes it to the first UnaryFunction, and then passes the result to the next one, passes that result to the next one, and so on.

What is FlatMap in RxJS?

The FlatMap operator transforms an Observable by applying a function that you specify to each item emitted by the source Observable, where that function returns an Observable that itself emits items. FlatMap then merges the emissions of these resulting Observables, emitting these merged results as its own sequence.


2 Answers

You'll want to filter the actual array and not the observable wrapped around it. So you'll map the content of the Observable (which is an Epic[]) to a filtered Epic.

getEpic(id: string): Observable<Epic> {   return this.getEpics()      .map(epics => epics.filter(epic => epic.id === id)[0]); } 

Then afterwards you can subscribe to getEpic and do whatever you want with it.

like image 117
Luka Jacobowitz Avatar answered Sep 22 '22 14:09

Luka Jacobowitz


You can do this using the flatMap and filter methods of Observable instead of the JS array filter method in map. Something like:

this.getEpics()      .flatMap((data) => data.epics) // [{id: 1}, {id: 4}, {id: 3}, ..., {id: N}]     .filter((epic) => epic.id === id) // checks {id: 1}, then {id: 2}, etc     .subscribe((result) => ...); // do something epic!!! 

flatMap will provide singular indices for filtering and then you can get on with whatever happens next with the results.

If TypeScript throws a error indicating you can't compare a string and a number regardless of your use of == in the filter just add a + before epic.id in the filter, per the Angular docs:

    .flatMap(...)     .filter((epic) => +epic.id === id) // checks {id: 1}, then {id: 2}, etc     .subscribe(...) 

Example:

https://stackblitz.com/edit/angular-9ehje5?file=src%2Fapp%2Fapp.component.ts

like image 26
mtpultz Avatar answered Sep 24 '22 14:09

mtpultz