Estoy intentando asociar un MatPaginator con un MatTable cuya propiedad de entrada dataSource simplemente se declara en la plantilla y no se suscribe desde el propio componente. Por ejemplo:
<table mat-table [dataSource]="allData$ | async" class="mat-elevation-z8">Normalmente, asociaría el paginador con la fuente de datos en el componente de la siguiente manera:
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; }); } } Desafortunadamente, esto no funcionará con el método anterior, ya que en realidad no estamos creando una nueva fuente de datos directamente, y no tenemos forma de asociar la fuente de datos y se suscribe automáticamente de forma declarativa a través de la canalización async .
Aquí hay un StackBlitz que muestra el problema: https://stackblitz.com/edit/angular-ivy-ebddd6?file=src/app/app.component.html .
Un mat-paginator se puede usar "independiente" o cuando tiene un objeto MatTableDataSource. La propiedad "datasource" de una mat-table puede ser: una matriz, un observable o un MatTableDataSource.
Para usar independiente, puede usar una variable de referencia de plantilla "pag" y una variable "longitud"
<mat-paginator #pag [length]="length" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons> </mat-paginator>Luego usa |slice in the way
<table mat-table [dataSource]="allData$|async |slice:pag.pageIndex*pag.pageSize: (pag.pageIndex+1)*pag.pageSize" class="mat-elevation-z8">La última pieza del rompecabezas es usar un grifo de tubería para obtener la longitud de la matriz.
allData$ = this.appService.getData().pipe( tap((res:any[])=>{ this.length=res.length }))Para evitar el error "AfterChecked", puede asignar a la variable allData$ en un ngOnInit encerrado en un setTimeOut
ngOnInit(){ setTimeout(()=>{ this.allData$ = this.appService.getData().pipe( tap((res:any[])=>{ this.length=res.length })) }) }Ver el stackblitz
No veo por qué no pudo convertirlo en MatTableDataSource aunque no se suscribió en el componente. Simplemente configuramos los datos dentro del map y devolvemos un MatTableDataSource , de esa manera puede adjuntarle el paginador. Para el ViewChild de ViewChild, debemos configurar static: true para que podamos acceder a él de inmediato, así que haría lo siguiente:
@ViewChild(MatPaginator, { static: true }) paginator: MatPaginator; allData$ = this.appService.getData().pipe( map((data) => { let dataSource = new MatTableDataSource(data); dataSource.paginator = this.paginator; return dataSource; }) );