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

如何解决Angular Material后端分页时上/下页按钮禁用问题

Angular Material后端分页按钮禁用问题

我正在测试Angular Material分页功能,采用后端分页模式,即每次请求对应页码的指定数量数据。例如总共有7条记录,第一页请求5条数据,加载显示正常;切换到第二页时加载剩余2条,但此时分页组件的上一页和下一页按钮被禁用。我检查了pageIndex、pageSize参数均正常,而一次性加载全部数据时分页功能可正常工作。


模板代码

<div class="mat-elevation-z8">
  <table mat-table [dataSource]="dataSource" matSort>

    <ng-container matColumnDef="photoPath">
      <th mat-header-cell *matHeaderCellDef> Photo </th>
      <td mat-cell *matCellDef="let element">
        <img [src]="element.photoPath" alt="Photo" width="50">
      </td>
    </ng-container>

    <ng-container matColumnDef="fullName">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Full Name </th>
      <td mat-cell *matCellDef="let element"> {{element.fullName}} </td>
    </ng-container>

    <ng-container matColumnDef="email">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Email </th>
      <td mat-cell *matCellDef="let element"> {{element.email}} </td>
    </ng-container>

    <ng-container matColumnDef="dateOfBirth">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> DateOfBirth </th>
      <td mat-cell *matCellDef="let element"> {{element.dateOfBirth | date}} </td>
    </ng-container>

    <ng-container matColumnDef="mobile">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Mobile </th>
      <td mat-cell *matCellDef="let element"> {{element.mobile}} </td>
    </ng-container>

    <ng-container matColumnDef="action">
      <th mat-header-cell *matHeaderCellDef> Action </th>
      <td mat-cell *matCellDef="let element">
        <button mat-button color="primary" (click)="editEmployee(element.id)">Edit</button>
        <button mat-button color="warn" (click)="deleteEmployee(element.id)">Delete</button>
      </td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
  </table>

  <mat-paginator [pageSizeOptions]="[5, 10, 20]"
               showFirstLastButtons
               [length]="totalRecords"  
               [pageSize]="searchValues.pageSize">
  </mat-paginator>
</div>

组件类代码

export class DataTableComponent{
  totalRecords: number = 100; // Declare totalRecords here
  displayedColumns: string[] = ['photoPath','fullName', 'email', 'mobile','dateOfBirth','action'];
  Employee!: Employee[];
  dataSource = new MatTableDataSource<Employee>(this.Employee);

  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;

  http = inject(HttpServiceService);
  router = inject(Router);
  dialog = inject(MatDialog);

  ngAfterViewInit() {
    // Now, the paginator is initialized, so we can safely load employees
    this.dataSource.paginator = this.paginator;
    this.dataSource.sort = this.sort;
    this.LoadEmployee(this.paginator.pageSize, this.paginator.pageIndex);
    this.paginator.page.subscribe((event: PageEvent) => {
      this.LoadEmployee(event.pageSize, event.pageIndex);
    });
    
  }
 LoadEmployee(pageSize: number, pageIndex: number) {
    this.http.GetAllEmployee(pageSize, pageIndex + 1).subscribe((response: any) => {
      this.dataSource.data = response.data.items;
      this.paginator.length = response.data.total;  // Set total number of records for paginator
      this.totalRecords = response.data.total; // Update totalRecords here
      this.paginator.pageSize = pageSize;
      console.log(this.paginator.pageSize, this.paginator.pageIndex, this.totalRecords)
    });
  }
}

问题原因及修复方案

1. 分页器长度绑定冲突

模板中mat-paginator已绑定[length]="totalRecords",但组件内又手动设置this.paginator.length = response.data.total,导致双向绑定冲突,分页器无法正确计算页码状态。

修复:移除组件内手动设置this.paginator.length的代码,仅通过totalRecords变量更新总条数。

2. PageSize绑定不一致

模板中mat-paginator绑定的是searchValues.pageSize,但组件初始化和请求时使用paginator.pageSize,还手动设置this.paginator.pageSize = pageSize,导致绑定值与控件实际值不匹配。

修复:统一使用组件内变量管理pageSize,替换模板中的searchValues.pageSize为组件内定义的pageSize变量。

3. 手动绑定paginator到DataSource

后端分页模式下,MatTableDataSource不需要绑定paginator,否则会触发自动分页逻辑,与手动分页冲突。

修复:移除this.dataSource.paginator = this.paginator代码。


修复后的完整代码

组件类代码

export class DataTableComponent{
  totalRecords: number = 0;
  pageSize: number = 5; // 统一管理pageSize
  displayedColumns: string[] = ['photoPath','fullName', 'email', 'mobile','dateOfBirth','action'];
  Employee!: Employee[];
  dataSource = new MatTableDataSource<Employee>(this.Employee);

  @ViewChild(MatPaginator) paginator!: MatPaginator;
  @ViewChild(MatSort) sort!: MatSort;

  http = inject(HttpServiceService);
  router = inject(Router);
  dialog = inject(MatDialog);

  ngAfterViewInit() {
    this.dataSource.sort = this.sort;
    // 初始化加载数据
    this.LoadEmployee(this.pageSize, 0);
    // 监听分页事件
    this.paginator.page.subscribe((event: PageEvent) => {
      this.pageSize = event.pageSize;
      this.LoadEmployee(event.pageSize, event.pageIndex);
    });
  }

  LoadEmployee(pageSize: number, pageIndex: number) {
    this.http.GetAllEmployee(pageSize, pageIndex + 1).subscribe((response: any) => {
      this.dataSource.data = response.data.items;
      this.totalRecords = response.data.total; // 仅更新绑定的totalRecords
      // 确保分页器页码同步
      if (this.paginator.pageIndex !== pageIndex) {
        this.paginator.pageIndex = pageIndex;
      }
      console.log(this.pageSize, this.paginator.pageIndex, this.totalRecords)
    });
  }
}

模板代码

<div class="mat-elevation-z8">
  <table mat-table [dataSource]="dataSource" matSort>

    <ng-container matColumnDef="photoPath">
      <th mat-header-cell *matHeaderCellDef> Photo </th>
      <td mat-cell *matCellDef="let element">
        <img [src]="element.photoPath" alt="Photo" width="50">
      </td>
    </ng-container>

    <ng-container matColumnDef="fullName">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Full Name </th>
      <td mat-cell *matCellDef="let element"> {{element.fullName}} </td>
    </ng-container>

    <ng-container matColumnDef="email">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Email </th>
      <td mat-cell *matCellDef="let element"> {{element.email}} </td>
    </ng-container>

    <ng-container matColumnDef="dateOfBirth">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> DateOfBirth </th>
      <td mat-cell *matCellDef="let element"> {{element.dateOfBirth | date}} </td>
    </ng-container>

    <ng-container matColumnDef="mobile">
      <th mat-header-cell *matHeaderCellDef mat-sort-header> Mobile </th>
      <td mat-cell *matCellDef="let element"> {{element.mobile}} </td>
    </ng-container>

    <ng-container matColumnDef="action">
      <th mat-header-cell *matHeaderCellDef> Action </th>
      <td mat-cell *matCellDef="let element">
        <button mat-button color="primary" (click)="editEmployee(element.id)">Edit</button>
        <button mat-button color="warn" (click)="deleteEmployee(element.id)">Delete</button>
      </td>
    </ng-container>

    <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
    <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
  </table>

  <mat-paginator [pageSizeOptions]="[5, 10, 20]"
               showFirstLastButtons
               [length]="totalRecords"  
               [pageSize]="pageSize">
  </mat-paginator>
</div>

内容的提问来源于stack exchange,提问作者SAFIQUL ISLAM UZZAL 203-15-144

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 08:32:35