Search code examples
angularjsrxjsobservableangularfirerxjs-observables

How to modify inner element of each Object emitted by observable before returning the outer observable


I am new to the whole concept of Observables and rxjs so this might be very obvious. But please help as I am desperate to learn

I have a funtion when a user clicks to show comments under a blog post

 showComments(){
    
    this.firestoreservice.getComments(this.job.id).subscribe( data =>{
      this.comments = data //type [] of comment objects with (message,posterID,timeposted...)
    })

    this._showcomments = true;

  }

This function calls a service function that returns an observable to my comments list for that job. In the subscribe to that observable is initialise a variable to hold all my comments. Before I do that however, is there a way to replace the posterID attribute of each comment with the matching username? See desired outcome below:

showComments(){
   
   this.firestoreservice.getComments(this.job.id).subscribe( data =>{

     //for each comment held in data, replace comment.posterID with getUserName(posterID)
     //getUserName(posterID) will also return an observable which emmits one string
     //then append comment to comments list (or add back in to data then destructively assign 
     //comments=data )
     
     this.comments = data //type [] of comment objects with (message,posterID,timeposted...)
   })

   this._showcomments = true;

 }

Solution

  • it'll look a little like this....

    this.firestoreservice.getComments(this.job.id).pipe(
      switchMap(comments => { // switchMap to subscribe to inner
        const getUsers$ = comments.map(comment => // array map comments into userName fetch
          this.firestoreservice.getUserName(comment.posterID).pipe(
            // once you have the username, rx map back into the comment with the username assigned
            map(userName => ({...comment, posterID: userName})),
            first() // use to complete after one emission to make forkJoin work
          )
        )
        return forkJoin(...getUsers$); // forkJoin them all together for parallel execution
      });
    ).subscribe(data => {
      this.comments = data // now just set the data
    })