Search code examples
arraysangulargoogle-cloud-firestoreangularfire2

AngularFire - How to push collection items into an array


I have an AngularFire collection query from firestore. I would like to push each of the returned items into my array. Below is what I have tried so far.

The result is that only the last item is entered into the array. If I remove this.myArr = []; from inside the query, all the results appear in the array on load. However, as you can imagine, when a new item is added, everything is readded to the array, opposed to the latest item. I assume that for each item, the array is being cleared, and then added to, hence the last item only being added.

How do I ensure that each item is added to the array, and not just the last?

 this.myArr = [];

   ...

  issueData() {
    this.albumCollection = this.afs.collection<any>(`album/albumID}/issues`, ref => {
      return ref.orderBy('order');
    });

    this.issues = this.albumCollection.snapshotChanges().pipe(
      map(actions => actions.map(a => {

        const data = a.payload.doc.data();
        const id = a.payload.doc.id;

        this.myArr = [];
        this.myArr.push({ id, ...data });

        return { id, ...data };

      }))
    );
}

HTML

 <div *ngFor="let issue of myArr"> a </div>

Solution

  • Why do you use a specific variable when your observable return already your array?

    issueData() {
        this.albumCollection = this.afs.collection<any>(`album/albumID}/issues`, ref => {
          return ref.orderBy('order');
        });
    
        this.issues = this.albumCollection.snapshotChanges().pipe(
            map(actions => actions.map(a => {
    
                const data = a.payload.doc.data();
                const id = a.payload.doc.id;
    
    
                return { id, ...data };
    
            }))
        );
    }
    

    Then, in your template, your subscribe to your observable to access the data:

    <div *ngFor="let issue of issues | async">{{issue | json}}</div>
    

    If your really need a variable to cache your result, you can use a tap operator (no need to push yourself data into the array):

    this.myArr = [];
    
    issueData() {
        this.albumCollection = this.afs.collection<any>(`album/albumID}/issues`, ref => {
          return ref.orderBy('order');
        });
    
        this.issues = this.albumCollection.snapshotChanges().pipe(
           map(actions => actions.map(a => {
    
             const data = a.payload.doc.data();
             const id = a.payload.doc.id;
    
    
             return { id, ...data };
    
           })),
           tap(data => this.myArr = data)
       );
    }
    

    But don't forget that you will have to subscribe to the observable to feed this.myArr, otherwise, it will stay empty.