0
votes

Takes the Angular Heroes and added a column of rating to it. The ratings contains values like good, very good, poor

Trying to take advantage of RxJS, filter operator to do this. When looking at https://www.learnrxjs.io/learn-rxjs/operators/filtering/filter example 2 it seems to be what I want

// RxJS v6+
import { from } from 'rxjs';
import { filter } from 'rxjs/operators';

//emit ({name: 'Joe', age: 31}, {name: 'Bob', age:25})
const source = from([
  { name: 'Joe', age: 31 },
  { name: 'Bob', age: 25 }
]);
//filter out people with age under 30
const example = source.pipe(filter(person => person.age >= 30));
//output: "Over 30: Joe"
const subscribe = example.subscribe(val => console.log(`Over 30: ${val.name}`));

however when using httpclient it does not work and has an error of "Property 'rating' does not exist on type 'Hero[]'.ts(2339)"

  isVeryGoodAd(): Observable<Hero[]> {
    return this.http.get<Hero[]>(this.heroesUrl).pipe(
      filter(heroes => heroes.rating === 'verygood')
      ) 
    ;
  }

How to use httpclient with RxJS filter to remove the unwanted values while returning an Observable which I would be able to subscribe to?

1

1 Answers

1
votes

The filter operator in the first example is not the same as the filter array function.

RxJS filter

RxJS filter will choose to let an observable value through based on a condition. It is a condition on the whole object.

The first example works because from emits each item sequentially, and then the filter operates on each item individually, discarding the ones that fail the condition. If you take the filter out, you will see that 2 items arrive in the subscribe method sequentially.

DEMO: https://stackblitz.com/edit/angular-ef3udf

The http request returns one value only. The filter is attempting to check a condition against the whole response, and is complaining that the rating property doesn't exist on an array (which is exactly what the error message says).

Array filter

Array filter will return elements in an array matching a condition. It checks a condition for each item in the array.

The solution

You are receiving one object from the HttpClient - the response. You want to conditionally remove some items. This is a transformation - you start off with an array and return a subset of that array.

For transformations in the pipe you use the RxJS map operator (not to be confused with the array function!). You can then apply the filter array function inside the RxJS map.

isVeryGoodAd(): Observable<Hero[]> {
  return this.http.get<Hero[]>(this.heroesUrl).pipe(
    map(heroes => heroes.filter(hero => hero.rating === 'verygood'))
  );
}