Nag*_*rma 33 pagination angular-material angular
我有2个组件.两者都有mat-table和paginator,并且分页对一个组件起作用,而不是为另一个组件工作,尽管代码类似.下面是我的html:
<div class="mat-elevation-z8">
<mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="col1">
<mat-header-cell *matHeaderCellDef mat-sort-header> Column1 </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.col1}} </mat-cell>
</ng-container>
<ng-container matColumnDef="col2">
<mat-header-cell *matHeaderCellDef mat-sort-header> Column2 </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.col2}} </mat-cell>
</ng-container>
<!-- Different columns goes here -->
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;">
</mat-row>
</mat-table>
<mat-paginator #scheduledOrdersPaginator [pageSizeOptions]="[5, 10, 20]"></mat-paginator>
</div>
Run Code Online (Sandbox Code Playgroud)
以下是我在component.ts中的代码:
dataSource: MatTableDataSource<any>;
displayedColumns = ['col1', 'col2', ... ];
@ViewChild('scheduledOrdersPaginator') paginator: MatPaginator;
@ViewChild(MatSort) sort: MatSort;
ngOnInit(): void {
// Load data
this.dataSource = new MatTableDataSource(somearray);
this.dataSource.paginator = this.paginator;
this.dataSource.sort = this.sort;
}
Run Code Online (Sandbox Code Playgroud)
类似的代码正在为其他组件工作,并且正确地使用分页呈现表,不知道此代码有什么问题.
任何帮助将非常感激
小智 49
我通过使用超时来围绕实例化解决了类似的问题.试试这个 :
setTimeout(() => this.dataSource.paginator = this.paginator);
Run Code Online (Sandbox Code Playgroud)
小智 44
在我的例子中,<mat-paginator>元素位于一个容器*ngIf上,该容器上有一个容器,在异步加载数据之前它不会呈现.这将导致this.paginator要undefined即使在ngAfterViewInit.这会导致它静默失败,因为MatTableDataSource您设置paginator为没有问题undefined.
解决方案是移动'd容器的<mat-paginator>外部*ngIf
希望这能帮助那些与我情况相同的人.
hop*_*sey 18
虽然选择的答案有效并解决了问题,但它仍然是一种解决方法.这是处理问题的正确和更优雅的方式.
尝试向AfterViewInit您的类添加接口,然后放入this.dataSource.paginator = this.paginatorinside ngAfterViewInit()方法
ngAfterViewInit() {
this.dataSource.paginator = this.paginator
}
Run Code Online (Sandbox Code Playgroud)
那么你就不必打电话给你setTimeout.
Muh*_*lal 18
第一个解决方案
将 mat-paginator 从 *ngIf div 内部移动到外部
第二种解决方案
在声明 MatPaginator 或 MatSort 时使用静态 false
@ViewChild(MatPaginator, {static: false}) paginator: MatPaginator;
@ViewChild(MatSort, {static: false}) sort: MatSort;
Run Code Online (Sandbox Code Playgroud)
小智 15
这是因为 this.paginator 在分配给 this.dataSource.paginator 时是未定义的。
如果您使用静态数据,这将起作用
@ViewChild(MatPaginator, {static: false}) paginator: MatPaginator; // For pagination
@ViewChild(MatSort, {static: false}) sort: MatSort; // For Sort
ngOnInit(): void {
this.dataSource.data = this.dataList; // Data list is data array
}
ngAfterViewInit(): void {
this.dataSource.paginator = this.paginator; // For pagination
this.dataSource.sort = this.sort; // For sort
}
Run Code Online (Sandbox Code Playgroud)
如果您使用动态数据(来自 API 的数据),这将起作用
用于分页
@ViewChild(MatPaginator, {static: false})
set paginator(value: MatPaginator) {
if (this.dataSource){
this.dataSource.paginator = value;
}
}
Run Code Online (Sandbox Code Playgroud)
对于排序
@ViewChild(MatSort, {static: false})
set sort(value: MatSort) {
if (this.dataSource){
this.dataSource.sort = value;
}
}
Run Code Online (Sandbox Code Playgroud)
作为旁注,我在运动中使用了 Angular 9。
设置数据源后,立即调用ChangeDetectorRef.detectChanges():
// First import ChangeDetectorRef & Material related stuff
import { ..., ChangeDetectorRef } from '@angular/core';
import { MatSort, MatTableDataSource, MatPaginator } from '@angular/material';
// Set properties in your component
@ViewChild(MatSort) sort: MatSort;
@ViewChild(MatPaginator) paginator: MatPaginator;
// Inject in constructor
constructor (..., private cdr: ChangeDetectorRef, ...) { ... }
// Set data source and invoke detectChanges()
this.dataSource = new MatTableDataSource (MY_DATA);
this.cdr.detectChanges();
// after that you can set other properties like
this.dataSource.sort = this.sort;
this.dataSource.paginator = this.paginator;
Run Code Online (Sandbox Code Playgroud)
我花了几个小时才弄清楚。
关键是this.dataSource = new MatTableDataSource<MyInterface>(Object.values(data));
然后设置this.dataSource.paginator = this.paginator;
我正在使用this.dataSource = data虽然我可以获取数据但分页不起作用。
再次你必须使用new MatTableDataSource
适用于 Angular 11。
小智 5
为了使其工作,我必须在从源中获取数据后设置分页器
getVariables() {
this.activeRoute.params.subscribe(params => {
if (params['id'] && (params['type'] === Type.CodeList)) {
this.dataService
.getItems(this.currentLanguage, params['id'])
.subscribe((items: any) => {
this.dataSource.data = this.items;
this.dataSource.paginator = this.paginator;
})
}
})
}
Run Code Online (Sandbox Code Playgroud)
分页器何时在视图中可用以及何时可以检索并附加到数据源的问题是这个问题的主要症结和常见的陷阱。此处建议的变通方法包括使用setTimeout()and ngAfterViewInit,就是这样的变通方法,即“让我们看看我们需要等待多少时间才能确保@ViewChild使用正确的分页器值设置我们的组件字段”。
正确的方法是将 附加@ViewChild到属性设置器并在使用有效分页器调用该设置器时尽快(并且经常)设置数据源分页器。
拥有单个数据源而不是每次加载都替换它也非常有用(正如我看到很多人所做的那样) - 只需将数据源绑定到 mat-table 并更新它的data字段。
<mat-table [dataSource]="dataSource" matSort>
<ng-container matColumnDef="col1">
<mat-header-cell *matHeaderCellDef mat-sort-header> Column1 </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.col1}} </mat-cell>
</ng-container>
<ng-container matColumnDef="col2">
<mat-header-cell *matHeaderCellDef mat-sort-header> Column2 </mat-header-cell>
<mat-cell *matCellDef="let row"> {{row.col2}} </mat-cell>
</ng-container>
<!-- Different columns goes here -->
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;">
</mat-row>
</mat-table>
<mat-paginator #scheduledOrdersPaginator [pageSizeOptions]="[5, 10, 20]"></mat-paginator>
</div>
Run Code Online (Sandbox Code Playgroud)
dataSource: MatTableDataSource<any> = new MatTableDataSource();
displayedColumns = ['col1', 'col2', ... ];
@ViewChild('scheduledOrdersPaginator') set paginator(pager:MatPaginator) {
if (pager) this.dataSource.paginator = pager;
}
@ViewChild(MatSort) set sort(sorter:MatSort) {
if (sorter) this.dataSource.sort = sorter;
}
ngOnInit(): void {
this.loadData().subscribe(somearray => { this.dataSource.data = somearray; });
}
Run Code Online (Sandbox Code Playgroud)
这种方法还应该解决分页器隐藏在*ngIf模板后面时延迟呈现的问题(此处的一位评论者指出)- 即使分页器呈现得很晚,它也会被发送到数据源。