Angular分页功能异常:加载后端数据后无法切换页面
Angular Material表格分页无法切换下页问题
我使用Angular Material的表格分页组件从后端拉取数据,基础配置如下:
dataSource = new MatTableDataSource<List_Product>; @ViewChild(MatPaginator) paginator: MatPaginator; this.dataSource = new MatTableDataSource<List_Product>(allProducts.products); this.dataSource.paginator = this.paginator;
目前能正常加载产品列表,但设置每页显示5条时无法切换到下一页,求排查原因。以下是完整代码:
list.component.ts
export class ListComponent extends BaseComponent implements OnInit, AfterViewInit { constructor(spiner: NgxSpinnerService, private productService: ProductService, private alertifyService: AlertifyService) { super(spiner) } displayedColumns: string[] = ['name', 'stock', 'price', 'createdDate', 'updatedDate']; dataSource = new MatTableDataSource<List_Product>; @ViewChild(MatPaginator) paginator: MatPaginator; async getProducts() { this.showSpinner(SpinnerType.SquareLoader); const allProducts: { totalProductCount: number; products: List_Product[] } = await this.productService.read(this.paginator ? this.paginator.pageIndex : 0, this.paginator ? this.paginator.pageSize : 5, () => this.hideSpinner(SpinnerType.BallSpinFadeRotating), errorMessage => this.alertifyService.message(errorMessage, { dismissOthers: true, messageType: MessageType.Error, position: Position.TopRight })) this.dataSource = new MatTableDataSource<List_Product>(allProducts.products); this.dataSource.paginator = this.paginator; console.log("paginator: " + this.dataSource.paginator.pageSize) } async pageChanged() { await this.getProducts(); } async ngOnInit() { await this.getProducts(); } }
list.component.html
<div class="mat-elevation-z8"> <table mat-table [dataSource]="dataSource"> <ng-container matColumnDef="name"> <th mat-header-cell *matHeaderCellDef> Name </th> <td mat-cell *matCellDef="let element"> {{element.name}} </td> </ng-container> <ng-container matColumnDef="stock"> <th mat-header-cell *matHeaderCellDef> Stock </th> <td mat-cell *matCellDef="let element"> {{element.stock}} </td> </ng-container> <ng-container matColumnDef="price"> <th mat-header-cell *matHeaderCellDef> Price </th> <td mat-cell *matCellDef="let element"> {{element.price}} </td> </ng-container> <ng-container matColumnDef="createdDate"> <th mat-header-cell *matHeaderCellDef> Created Date </th> <td mat-cell *matCellDef="let element"> {{element.createdDate}} </td> </ng-container> <ng-container matColumnDef="updatedDate"> <th mat-header-cell *matHeaderCellDef> Updated Date </th> <td mat-cell *matCellDef="let element"> {{element.updatedDate}} </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table> <mat-paginator (page)="pageChanged()" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons aria-label="Select page of periodic elements"> </mat-paginator> </div>
product.service.ts
async read(page: number = 0, size: number = 5, successCallBack?: () => void, errorCallBack?: (errorMessage: string) => void): Promise<{ totalProductCount: number; products: List_Product[] }> { const promiseData: Promise<{ totalProductCount: number; products: List_Product[] }> = firstValueFrom(this.HttpClientService.get<{ totalProductCount: number; products: List_Product[] }>({ controller: "products", queryString: `page=${page}&size=${size}` })); promiseData.then(d => successCallBack()) .catch((errorResponse: HttpErrorResponse) => errorCallBack(errorResponse.message)) return await promiseData; }
问题原因及修复方案
1. 未设置分页总条数
Angular Material分页组件需要知道总数据量才能正确计算页码范围和切换逻辑,当前仅传入了当前页数据,未告知分页器总产品数。
修复: 在getProducts方法中添加总条数绑定:
this.dataSource = new MatTableDataSource<List_Product>(allProducts.products); this.dataSource.paginator = this.paginator; this.paginator.length = allProducts.totalProductCount; // 新增此行
2. 重复创建MatTableDataSource实例
每次调用getProducts都重新创建dataSource,会导致分页器的状态绑定异常、状态丢失。应复用同一个实例,仅更新数据内容。
修复:
- 初始化时创建一次实例:
dataSource = new MatTableDataSource<List_Product>([]); - 在
getProducts中替换数据创建逻辑:// 替换原两行创建代码 this.dataSource.data = allProducts.products;
3. 分页器初始化时机问题
组件实现了AfterViewInit但未使用,@ViewChild获取的paginator在ngOnInit阶段可能未完成初始化,导致首次调用时参数获取异常。
修复:
- 在
ngAfterViewInit中完成分页器的首次绑定:ngAfterViewInit() { this.dataSource.paginator = this.paginator; } - 优化
getProducts中的参数获取逻辑:const pageIndex = this.paginator?.pageIndex ?? 0; const pageSize = this.paginator?.pageSize ?? 5; const allProducts = await this.productService.read(pageIndex, pageSize, () => this.hideSpinner(SpinnerType.BallSpinFadeRotating), errorMessage => this.alertifyService.message(errorMessage, { dismissOthers: true, messageType: MessageType.Error, position: Position.TopRight }));
4. 分页事件参数优化
直接从分页事件中获取参数,避免依赖paginator实例的状态:
- 修改模板中的事件绑定:
<mat-paginator (page)="pageChanged($event)" [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons aria-label="Select page of periodic elements"> </mat-paginator> - 修改
pageChanged方法:async pageChanged(event: PageEvent) { this.showSpinner(SpinnerType.SquareLoader); const allProducts = await this.productService.read(event.pageIndex, event.pageSize, () => this.hideSpinner(SpinnerType.BallSpinFadeRotating), errorMessage => this.alertifyService.message(errorMessage, { dismissOthers: true, messageType: MessageType.Error, position: Position.TopRight })); this.dataSource.data = allProducts.products; this.paginator.length = allProducts.totalProductCount; }
内容的提问来源于stack exchange,提问作者Olcaytp
相关产品推荐
相关产品推荐

