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" >
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.
CodePudding user response:
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;
})
);
CodePudding user response:
A mat-paginator can be used "standalone" or when you has a MatTableDataSource object. The property "datasource" of a mat-table can be: an array, an observable or a MatTableDataSource.
To use standalone, you can use a template reference variable "pag" and a variable "length"
<mat-paginator #pag [length]="length"
[pageSizeOptions]="[5, 10, 20]"
showFirstLastButtons>
</mat-paginator>
Then use |slice in the way
<table mat-table [dataSource]="allData$|async
|slice:pag.pageIndex*pag.pageSize:
(pag.pageIndex 1)*pag.pageSize"
>
The last piece of the jigsaw is use pipe tap to get the length of the array
allData$ = this.appService.getData().pipe(
tap((res:any[])=>{
this.length=res.length
}))
To avoid the error "AfterChecked" you can asign to the variable allData$ in a ngOnInit enclosed in a setTimeOut
ngOnInit(){
setTimeout(()=>{
this.allData$ = this.appService.getData().pipe(
tap((res:any[])=>{
this.length=res.length
}))
})
}
See the stackblitz