Ad

Use RXJS And AsyncPipe Instead Of Observable.subscribe

- 1 answer

In my firebase (angularfire2) app I want return document for each element of collection. For this I use Observables + .subscribe(). But I want to get alternative using RXJS and AsyncPipe.

I tried to use next RXJS chains:

this.shortlisted$ = this.db.collection(`interestingStartups`).valueChanges().pipe(mergeMap(actions => actions.map(el => {
 return this.db.doc(`startups/${(<any>el).startupUid}`).valueChanges().pipe(mergeMap(el => of([el])));
})));

And use *ngFor="let s of shortlisted$ | async" inside HTML template. But it not works. Angular shows next error "Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays"

My current code (Observables + .subscribe) which works:

this.db.collection('interestingStartups').valueChanges().subscribe((el:any) => {
 el.forEach(is => {
  this.db.doc('startups/' + is.startupUid).get().subscribe(s => {
   this.shortlisted.push(s.data());
  })
 })        
});

And I just use pure *ngFor without AsyncPipe, i.e. *ngFor="let s of shortlisted"

I want assign result into this.shortlisted using RXJS operators like mergeMap or similar. At the current moment I was not able to find working solution for this

Please help!

Ad

Answer

This one should work.

this.shortlisted$ = this.db.collection('interestingStartups').valueChanges().pipe(
  switchMap(el => combineLatest(
    el.map(is => this.db.doc('startups/' + is.startupUid).get())
  ))
);

It starts by getting the list of interestign startups, then for each startup, it gets the document for the startup, and it uses combineLatest to concatenate them.

Ad
source: stackoverflow.com
Ad