firebasegoogle-cloud-firestorepaginationangular-material-tablecursors

Issues with the material table updating when using paginator


I've searched and I've searched and I've searched, I can't find an answer to this.

I am using Angular Firestore to fetch data (tried both snaphotChanges and valueChanges). The code works.

However, if the data changes on the backend, the material table row on the UI only refreshes automatically when either I am showing all the data or if I disable paging. However, when paging is enabled, the UI resorts to show that the data got updated, but it does not refresh the cell value until I move the cursor on the row to force a refresh. I don't know if it's a bug or if I am doing something wrong.

I made a video showing what happens: https://youtu.be/SN6EFc6Vqm8

// Have this in my service. It works  
getContactsByLimit(limit) {
    return this.afs
      .collection("users")
      .doc(this.user.currentUserId)
      .collection("contacts", ref =>
        ref
          .orderBy("id", "desc")
          .limit(limit)
      )
      .valueChanges();
  }

  // The paginator declaration
  @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;

// This works
this.contactsSubscription = this.contactsvc
      .getContactsSnapshotChangesByLimit(3) 
      .subscribe(contacts => {
        // This works, I get new data.
        this.dataSource.data = contacts;  
      });

// HTML template
<mat-paginator class="paginator" 
  [length]="15"  // This breaks the refresh
  [pageSize]="3" 
  [pageSizeOptions]="[2,3,5]" 
  (page)="pageEvent($event)"></mat-paginator>

// The automatic refresh does not work if I set 
// the length to be > 3 in this case (unless I move 
// the mouse on the table). 

The UI should refresh with new data whether the length > pageSize or not.


Solution

  • Figured it out. I was using trackBy to track by ID. I added a timestamp field in my document and started tracking by timestamp.

     <table [dataSource]="dataSource" [trackBy]="trackByTimestmamp" mat-table>
    

    and

    trackByTimestmamp(index, item) {
        return item.timestamp;
    }
    

    This forces the material table to update the table when the timestamp changes.