Search code examples
angularpaginationangular-material-tablemat-pagination

Angular mat-paginator displaying full async dataSource


I would expect i'm missing something obvious here, and I would appreciate any support or insight provided...

I have this mat-table

component.html

  <mat-paginator></mat-paginator>

  <table mat-table [dataSource]="ds" class="mat-elevation-z8" matSort>

    <ng-container matColumnDef="id">
      <th mat-header-cell *matHeaderCellDef> MetaverseID </th>
      <td mat-cell *matCellDef="let element"> {{element.id}} </td>
    </ng-container>

    <ng-container matColumnDef="totalLots">
      <th mat-header-cell *matHeaderCellDef> Total lots </th>
      <td mat-cell *matCellDef="let element"> {{element.totalLots}} </td>
    </ng-container>

    <ng-container matColumnDef="investment">
      <th mat-header-cell *matHeaderCellDef> Investment </th>
      <td mat-cell *matCellDef="let element"> {{element.investment}} </td>
    </ng-container>

    <ng-container matColumnDef="investmentValue">
      <th mat-header-cell *matHeaderCellDef> Investment Value </th>
      <td mat-cell *matCellDef="let element"> {{element.investmentValue}} </td>
    </ng-container>

    <ng-container matColumnDef="mvShare">
      <th mat-header-cell *matHeaderCellDef> Metaverse Share </th>
      <td mat-cell *matCellDef="let element"> {{element.mvShare}} </td>
    </ng-container>

    <ng-container matColumnDef="valueIndex">
      <th mat-header-cell *matHeaderCellDef> Value Index </th>
      <td mat-cell *matCellDef="let element"> {{element.valueIndex}} </td>
    </ng-container>
    

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
  </table>

which goes with this typsescript file

component.ts

imports...
import { MatTable, MatTableDataSource } from '@angular/material/table';
import {MatPaginator} from '@angular/material/paginator';

@Component({
  selector: 'app-main-dataset',
  templateUrl: './main-dataset.component.html',
  styleUrls: ['./main-dataset.component.scss']
})
export class MainDatasetComponent implements OnInit {

  displayedColumns: string[] = ['id', 'totalLots', 'investment', 'investmentValue', 'mvShare', 'valueIndex'];
  
  constructor() { }

  @Input() owners: { [key: string]: MVLot[] } = {};

  @ViewChild(MatTable) table: MatTable<any>;
  @ViewChild(MatPaginator) pag: MatPaginator;

  output: OutputRecord[] = []
  ds = new MatTableDataSource<any>();

  ngOnInit(): void {
  }

  ddSelect(target: any) {
    if ("the right dropdown value is selected") {
      this.valueSet = true;

      this.ids.forEach(w => {

        // some finessing logic

        this.output.push(out);
        
      });

      this.output.sort(function (a, b) {
        return b.totalLots - a.totalLots;
      });


      this.ds.paginator = this.pag;
      this.ds = new MatTableDataSource(this.output);
    }

    if (this.valueSet) {
      this.valueSet = false;
    }
  }
}

it feels like there's something missing connecting the table to the pagination element.

The datasource element isn't populated until the user has selected a value in the dropdown. The page loads the table, but pagination never seems to acknowledge the changes.

enter image description here

The end result is that the pagination control seems to have no connection to the table. I imagine somewhere in the mat-table lib these two elements are linked, since i didn't see any reference to this in the mat-talbe documentation. https://material.angular.io/components/table/examples

What am I missing that creates this disconnect between these two controls? Is it a problem that my data is populated after initial page load?


Solution

  • So, in the end, I was able to get this working using this code:

    [other imports...]
    import { MatPaginator } from '@angular/material/paginator';
    
    @Component({
      selector: 'app-main-dataset',
      templateUrl: './main-dataset.component.html',
      styleUrls: ['./main-dataset.component.scss'],
    })
    
    export class MainDatasetComponent implements AfterViewInit, OnChanges {
    
      allLandsDataSource = new MatTableDataSource<OutputRecord>(this.output);
      openLotsDataSource = new MatTableDataSource<MVLot>(this.openLots);
    
      constructor(private cdr: ChangeDetectorRef) { 
        this.allLandsDataSource = new MatTableDataSource(this.output);
        this.openLotsDataSource = new MatTableDataSource(this.openLots);
      }
    
      @ViewChild(MatTable) table: MatTable<any>;
      @ViewChild(MatPaginator) paginator: MatPaginator;
    
      ngAfterViewInit() {
        this.allLandsDataSource.paginator = this.paginator;
        this.allLandsDataSource.sort = this.sort;
    
        this.openLotsDataSource.paginator = this.paginator;
        this.openLotsDataSource.sort = this.sort;
    
        this.cdr.detectChanges();
      }
    
      ddSelect(target: any) {
            if (this.wallets.length > 0) {
              if (!this.whaleTableDefined) {
                this.whaleTableDefined = true;
          
                this.wallets.forEach(w => {
                  [some logic]
                  this.output.push(out);
                  
                });
          
                this.output.sort(function (a, b) {
                  return b.totalLots - a.totalLots;
                });
              }
          
              this.allLandsDataSource = new MatTableDataSource(this.output);
              this.allLandsDataSource.paginator = this.paginator;
            }
        
    
      }
    }
    
    

    By setting paginator on the dataSource after, this worked.