FacundoGFlores FacundoGFlores - 22 days ago 10
TypeScript Question

Subscribe to event emitter when array is loaded

I have the following code:

this.itemsService.getItems()
.subscribe(i => this.items = i);


But, the user can select a type of item, so I have an event emitter for this:

this.typeofitems.selectedType.subscribe(type => this.type = type);


and it is working well.

Now I want to filter the list of items
this.items
with the
filter function
. The problem is, I don't know when the loading of items is completed, altough if I put a log in the subscription:

this.itemsService.getItems()
.subscribe(i => {this.items = i; console.log("completed");});


it indicates me that's completed. So I tried:

this.itemsService.getItems()
.subscribe(i => {
this.items = i;
this.typeofitems.selectedType.subscribe(type => {
this.type = type;
this.filterByType();
});
});

filterByType() {
this.itemsfilteredByType = this.items.filter(i => i.type === this.type)
}


But it is not working. So I think I can not subscribe inside a subscriptor.
How can I achieve it?

Answer

Note that you're using = instead of == in the filter() callback so make sure this wasn't the problem.

Anyway, you can use operator combineLatest() that emits a value every time any of it's sources emit a value (while at least one value from each source has to be emitted):

function getItems() {
  return Observable.of([{type: 1, val: 345}, {type: 2, val: 107}, {type: 1, val: 926}, {type: 2, val: 456} ]);
}

let typeOfItems = new Subject();

Observable.combineLatest(getItems(), typeOfItems)
  .subscribe(vals => {
    let [items, typeOfItem] = vals;

    let results = items.filter(i => i.type == typeOfItem);
    console.log(results);
  });

typeOfItems.next(2);

This filters items by type == 2 and prints to console:

[[object Object] {
  type: 2,
  val: 107
}, [object Object] {
  type: 2,
  val: 456
}]

It works thanks to combineLatest() which first receives all items and then I tell it to filter them by type == 2 using typeOfItems.next(2); which triggers call to the callback for combineLatest() that uses Array.filter() to actually filter and print filtered items (note this is Array.fitler() and not Observable.filter()).

See live demo: https://jsbin.com/nenosiy/5/edit?js,console

Btw, of course you can subscribe() inside another subscribe() callback. Just remember you have to manually unsubscribe previous subscribtions.

See a very similar question: Dynamically filtering rxjs stream

Comments