0

I have now this piece of code to filter an observable.

listings$: Observable<Listing[]>;

this.listings$ = this.firestore
      .getListings()
      .pipe(map(listings => listings.filter(listing => listing.promoted === true)));

Which works fine, but I want to make full use of rxjs instead of using the filter on the array.

The this.firestore.getListings() function returns Observable<Listing[]>, and this.listings$ must be Observable<Listing[]> as well.

I tried different approaches, and struggling with this for a while. Maybe you can help me. I'm still "fresh" to angular and rxjs.

this.listings$ = this.firestore.getListings().pipe(
      mergeMap(listings => listings),
      filter(listing => listing.promoted === true)
    );

Type Observable<Listing> is not assignable to type Observable<Listing[]>.

I might be doing something wrong with the mergeMap operator, or even it is not correct operator to use in this case.

I tried to adjust the code from this post. The flatMap operator seem to be changed to mergeMap. But it's still not working.

4
  • 3
    Using rxjs map and array filter is absolutely a proper way of doing it. Don't go out of your way to change it. Commented Jun 13, 2018 at 18:58
  • It looks like the error is caused by the type given to this.listings$. Outside of the code shown, you must adjust the code to match an observable stream of individual listing objects. I guess that form is more convenient for your view? Commented Jun 13, 2018 at 20:29
  • @eric99 I didn't add this part of code in my post. But however it is listings$: Observable<Listing[]>; Commented Jun 13, 2018 at 22:28
  • Thanks for that info. So why exactly are you trying to flatten the observable? Commented Jun 14, 2018 at 1:49

1 Answer 1

0

Well, this depends on how you want to use the this.listings$ Observable. Using mergeMap(listings => listings) is correct and it turns Observable<Listing[]> into Observable<Listing> but you said you want to use RxJS filter() operator and you want to have Observable<Listing[]> at the end anyway.

One way could be using take(1) and toArray() operators. toArray() will accumulate all emissions from its source into a single array and when the source competes it emits the array.

this.listings$ = this.firestore.getListings().pipe(
  take(1),
  mergeMap(listings => listings),
  filter(listing => listing.promoted === true),
  toArray(),
);

Note that this listings$ Observable will emit just once and won't react to any subsequent emissions from this.firestore.getListings().

Personally, I'd actually use what you had pipe(map(listings => listings.filter(...))) because this is just easier to use.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. this.listings$ is Observable<Listing[]> so I can subscribe to it and get listings displayed over time as they are added, so take(1) is not what I want. I will mark your answer as accepted because you actually covered more than I expected someone would answer.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.