How to use the output of an observable to filter another

4.2k views Asked by At

So I have two observables, one returns the current category, and the other products. I wish to filter the products based on category.

This is in Angular 2, so I really wish my ng2-view to be the subscriber (via the async pipe).

Something like this simple example:

let category$ = Observable.of({id: 1});
let products$ = Observable.from([{name: 'will be included', cat_ids: [1, 5]}, {name: 'nope', cat_ids: [2, 3]}, {name: 'also yep', cat_ids: [1, 7]}]);

return products$
  .toArray()
  .filter(prod => {
    return prod.cat_id.some(id => id === <how do I get the value of the category observable here?>)
  });

Maybe the answer is simple, but it eludes me.

1

There are 1 answers

4
Sergey Sokolov On BEST ANSWER

You need to join these two streams e.g. with combineLatest:

let category$ = Observable.of({id: 1});
let products$ = Observable.from([{name: 'will be included', cat_ids: [1, 5]}, {name: 'nope', cat_ids: [2, 3]}, {name: 'also yep', cat_ids: [1, 7]}]);

return Observable.combineLatest(products$, category$)
  .map(([products, category]) => {
    return products.filter(prod => prod.cat_id.some(id => id === category.id);
  });

Update

As @olsn pointed out with Observable.from you get stream of events not stream of array of events. Hence the solution should be:

let category$ = Observable.of({id: 1});
let products$ = Observable.from([{name: 'will be included', cat_ids: [1, 5]}, {name: 'nope', cat_ids: [2, 3]}, {name: 'also yep', cat_ids: [1, 7]}]);

return Observable.combineLatest(products$, category$)
  .filter(([product, category]) => {
    return product.cat_id.some(id => id === category.id);
  })
  .map(([product, category]) => product);