Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use the output of an observable to filter another

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.

like image 636
DarkNeuron Avatar asked Dec 27 '16 10:12

DarkNeuron


1 Answers

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);
like image 195
Sergey Sokolov Avatar answered Oct 25 '22 14:10

Sergey Sokolov