You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.29 04:36:04