Search code examples
angularfirebaserxjsangularfire2

Use RXJS and AsyncPipe instead of Observable.subscribe


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!


Solution

  • 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.