Search code examples
angulartypescriptangularfire

Is there a better way to update single items in ngFor Angular?


What's working for me:

invoke.directive.ts

export class InvokeDirective {

  @Output() invoke = new EventEmitter();
  ngAfterContentInit() {
    this.invoke.emit(null);
  }

}

posts.component.html

<ul class="list-group">
        <li class="list-group-item" *ngFor="let deal of deals | async, index as i"
        (invoke)="getOwnerData(deal.ownerId)">
          {{ deal.title }} <span class="badge bg-primary" style="color: white; float: right;">{{userNamesArray[i]}}</span>
        </li>
      </ul>

posts.component.html

getOwnerData(userId : string) {
    this.ownerDoc = this.userFirestore.doc<any>('users/' + userId);
    this.dealOwner = this.ownerDoc.valueChanges();

    this.dealOwner.subscribe(res => {
      //console.log(res)
      this.ownerName = res.name;
      this.userNamesArray.push(res.name)

      console.log(this.userNamesArray)
    })
  }

This is working for me but I just want to know if there is a better way. I tried using one value to bind to but it always updated with the last value making them all the same. Your help will be much appreciated. Cheers!


Solution

  • this.deals = this.dealsCollection.snapshotChanges().pipe(
         map(actions => actions.map(a => {
            const data = a.payload.doc.data();
            const id = a.payload.doc.id;
            return { id, ...data };
            })
    ),
    switchMap(ownerDeals =>
       // do this all in parallel (can use concat instead to do one at a time)
          forkJoin(ownerDeals.map(ownerDeal =>
       // create a new observable for each deal
          this.afs.doc<any>(`users/${ownerDeal.ownerId}`).valueChanges().pipe(
       // only take 1 value
        take(1),
       // merge the deal and user info
        map(user => ({
           ...ownerDeal,
           userName: user.name
        }))
         )
       ))
      )
     );
    

    all you need is combination of forkeJoin, and switchMap, and update user-name with ownerID and return combine data. so no need to call extra functionality.