Search code examples
angularangular-materialangular-material-tableangular-material-paginator

How do I associate a MatPaginator with a MatTable taking a declarative data source exclusively in the template?


I am attempting to associate a MatPaginator with a MatTable who's dataSource input property is simply declared in the template, and not subscribed to from within the component itself. For example:

<table mat-table [dataSource]="allData$ | async" class="mat-elevation-z8">

Normally, I would associate the paginator with the data source in the component like so:

export class AppComponent {
  @ViewChild(MatPaginator) set paginator(paginator: MatPaginator) {
    if (paginator) {
      this.dataSource.paginator = paginator;
    }
  }
  dataSource;
  displayedColumns = ['first_name', 'last_name', 'email', 'ip_address'];

  constructor(private appService: AppService) {}

  ngOnInit() {
    this.appService.getData().subscribe((data) => {
      this.dataSource = new MatTableDataSource(data);
      this.dataSource.paginator = this.paginator;
    });
  }
}

Unfortunately this will not work with the former method, as we are not actually creating a new datasource directly, and have no way to associate the data source and is automatically subscribed declarative via the async pipe.

Here is a StackBlitz showing the issue: https://stackblitz.com/edit/angular-ivy-ebddd6?file=src/app/app.component.html.


Solution

  • I don't see why you couldn't make it MatTableDataSource though not subscribing to it in the component. We just set the data inside map and return a MatTableDataSource, that way you can attach the paginator to it. For the ViewChild matpaginator we need to set static: true so that we can access it immediately, so I would do:

    @ViewChild(MatPaginator, { static: true }) paginator: MatPaginator;
    
    allData$ = this.appService.getData().pipe(
      map((data) => {
        let dataSource = new MatTableDataSource(data);
        dataSource.paginator = this.paginator;
        return dataSource;
      })
    );
    

    STACKBLITZ