Angular Mat Table远程数据源加载后排序与分页功能失效问题
问题原因
- 视图查询时机错误:@ViewChild获取的MatSort、MatPaginator实例在constructor执行时还未完成初始化,此时赋值给dataSource的sort和paginator属性均为undefined
- 动态元素未适配:表格、排序、分页器组件都被
*ngIf="items$ | async"包裹,只有接口请求成功后元素才会渲染,默认的@ViewChild查询无法捕获到延迟生成的元素 - 分页器多余配置:手动给mat-paginator绑定[length]属性会覆盖MatTableDataSource的自动长度计算逻辑,导致分页功能异常
修复方案
修正后的TS代码
import { Component, ViewChild, AfterViewInit } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { MatPaginator } from '@angular/material/paginator'; import { MatSort } from '@angular/material/sort'; import { MatTable } from '@angular/material/table'; import { MatTableDataSource } from '@angular/material/table'; import { Observable } from 'rxjs'; import { map, tap } from 'rxjs/operators'; import { environment } from 'src/environments/environment'; export class DummyTableComponent implements AfterViewInit { // 用setter适配动态渲染的元素,元素生成后自动赋值给dataSource @ViewChild(MatPaginator) set paginator(paginator: MatPaginator) { if (paginator) this.dataSource.paginator = paginator; } @ViewChild(MatSort) set sort(sort: MatSort) { if (sort) this.dataSource.sort = sort; } @ViewChild(MatTable) table!: MatTable<any>; items$!: Observable<any>; dataSource: MatTableDataSource<any> = new MatTableDataSource<any>(); displayedColumns = ['title', 'status']; constructor(private http: HttpClient) { this.items$ = this.http.get<any>(`${environment.apiUrl}/items`) .pipe( map((retval: any) => retval.items), tap(retval => { this.dataSource.data = retval; }) ); } ngAfterViewInit(): void { // 视图初始化兜底赋值逻辑 if (this.dataSource.sort && this.dataSource.paginator) return; this.dataSource.sort = this.sort; this.dataSource.paginator = this.paginator; } }
修正后的HTML代码
<div class="mat-elevation-z1" *ngIf="items$ | async"> <table mat-table class="full-width-table" matSort [dataSource]="dataSource"> <ng-container matColumnDef="title"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Title </th> <td mat-cell *matCellDef="let element"> {{element.title}} </td> </ng-container> <ng-container matColumnDef="status"> <th mat-header-cell *matHeaderCellDef mat-sort-header> Status </th> <td mat-cell *matCellDef="let element"> {{element.status}} </td> </ng-container> <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr> <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr> </table> <mat-paginator #paginator [pageIndex]="0" [pageSize]="10" [pageSizeOptions]="[1,5, 10, 20]" aria-label="Select page"> </mat-paginator> </div>
内容的提问来源于stack exchange,提问作者Aeseir
相关产品推荐
相关产品推荐

