Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2: How to use Observable filter

I have a service that calls the API like this:

return this._http
        .post(appSettings.apiUrl + 'SomeController/SomeAction', params, {withCredentials: true, headers: this.headers})
        .timeoutWith(appSettings.maxTimeHttpCalls, Observable.defer(() => Observable.throw(this._feedbackService.timeout())))
        .map((response: Response) => response.json().data);

Now I want to implement a filter function on that call using rxjs/add/operator/filter, but I can't get it to work properly.

This is the approach I have taken:

return this._http
        .post(appSettings.apiUrl + 'SomeController/SomeAction', params, {withCredentials: true, headers: this.headers})
        .timeoutWith(appSettings.maxTimeHttpCalls, Observable.defer(() => Observable.throw(this._feedbackService.timeout())))
        .filter(response => response.json().data.Type === 5)
        .map((response: Response) => response.json().data);

But no matter what I filter on, the ngFor loop produces nothing as long as the filter is in there. If I remove it, everything works as expected.

Am I supposed to add the filter before or after the map?

Can I filter on the response JSON like that, or do I need to use another syntax?

Example JSON

Here's an example of what the response JSON looks like:

data: [
    {
        "Type": 5,
        "Description": "Testing",
        "ID": "001525"
    }
]
like image 981
Glenn Utter Avatar asked Oct 18 '16 05:10

Glenn Utter


People also ask

How does RxJS filter work?

RxJS filter() operator is a filtering operator used to filter items emitted by the source observable according to the predicate function. It only emits those values that satisfy a specified predicate. The RxJS filter() operator is like the well-known Array Array . prototype.

What is filter operator in Angular?

The Filter Operator in Angular filters the items emitted by the source Observable by using a condition (predicate). It emits only those values, which satisfies the condition and ignores the rest.

How we can use observable in Angular?

Usage. The basic usage of Observable in Angular is to create an instance to define a subscriber function. Whenever a consumer wants to execute the function the subscribe() method is called. This function defines how to obtain messages and values to be published.


2 Answers

Whether filter() should be before or after map() depends on what you want to do.

I guess in your case map() should go before filter() because you want to first decode data from JSON and then filter it. The way you have it now won't return anything if the condition in filter() resolves to false because you're using in on the entire response. Maybe this is what you're going for...

I don't know what your response structure is but I'd go with something like this which makes more sense:

map((response: Response) => response.json().data),
filter(data => data.Type === 5),

Edit:

I'd use concatMap() with from() to transform the array to an Observable stream:

pipe(
  map(content => response.json().data),
  concatMap(arr => Observable.from(arr)),
  filter(item => item.Type === 5),
).subscribe(val => console.log(val));

See live demo: http://plnkr.co/edit/nu7jL7YsExFJMGpL3YuS?p=preview

Jan 2019: Updated for RxJS 6

like image 117
martin Avatar answered Oct 21 '22 20:10

martin


Here another sample based on @martin's answer:

  public searchMediData(searchtearm: string) : Observable<MediData[]> 
  {  

    return this.http
               .get(this.url)
               .map(response => { 
                  let data = response.json();
                  let medidata = data as MediData[];
                  return medidata;
                })
                .concatMap(array => Observable.from(array))
                .filter(medi => {
                        let searchTearmUpperCase = searchtearm.toUpperCase();
                        let mediNameUpperCase = medi.Name.toUpperCase();                       
                        return mediNameUpperCase.includes(searchTearmUpperCase);
                 })
                .toArray();
  }
like image 3
yonexbat Avatar answered Oct 21 '22 18:10

yonexbat