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

Angular子组件mat-paginator与父子传值DataSource失效问题

解决Mat-Paginator分页不生效问题

问题根源分析

你的代码存在几个核心问题导致分页失效:

  • 子组件ngOnInit中直接用tableData重新创建dataSource,完全覆盖了父组件传入的数据源,父组件更新数据后子组件根本接收不到
  • @ViewChild(MatPaginator)在ngOnInit阶段还未完成DOM初始化,此时绑定分页器属于无效操作
  • 分页器的length硬写死为450,未与实际数据长度关联
  • 同时存在tableData和dataSource两个输入参数,逻辑冲突导致数据源混乱

分步解决方案

1. 修复子组件逻辑(table.component.ts)

移除覆盖父组件数据源的代码,改用生命周期钩子正确绑定分页器,并监听数据源变化:

import { Component, Input, OnInit, ViewChild, AfterViewInit, OnChanges, SimpleChanges } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';
import { ChangeDetectorRef } from '@angular/core';

export class TableComponent<T> implements OnInit, AfterViewInit, OnChanges {
  @ViewChild(MatPaginator) paginator!: MatPaginator;

  @Input()
  tableColumns: Array<Column> = [];

  @Input()
  dataSource: MatTableDataSource<T> = new MatTableDataSource();

  displayedColumns: Array<string> = [];

  constructor(private cdr: ChangeDetectorRef) {}

  ngOnInit(): void {
    this.displayedColumns = this.tableColumns.map((c) => c.columnDef);
  }

  ngAfterViewInit(): void {
    // 视图初始化完成后才能拿到paginator实例
    this.bindPaginator();
  }

  ngOnChanges(changes: SimpleChanges): void {
    // 监听父组件传入的dataSource变化,重新绑定分页器
    if (changes['dataSource']?.currentValue) {
      this.bindPaginator();
    }
  }

  private bindPaginator(): void {
    if (this.paginator && this.dataSource) {
      this.dataSource.paginator = this.paginator;
      this.cdr.detectChanges();
    }
  }
}

2. 修正分页器绑定(table.component.html)

把分页器的length绑定到实际数据长度,同时确保mat-table正确关联dataSource:

<table mat-table [dataSource]="dataSource">
  <!-- 动态生成列(根据你的tableColumns定义) -->
  <ng-container *ngFor="let column of tableColumns" [matColumnDef]="column.columnDef">
    <th mat-header-cell *matHeaderCellDef>{{ column.header }}</th>
    <td mat-cell *matCellDef="let element">{{ column.cell(element) }}</td>
  </ng-container>
  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

<mat-paginator 
  [length]="dataSource.filteredData.length"  
  [pageSize]="5" 
  [pageSizeOptions]="[5, 10, 20, 100]"
  aria-label="Select page of periodic elements">
</mat-paginator>

3. 优化父组件数据更新逻辑(可选)

父组件更新数据时,优先修改现有dataSource的data属性而非创建新实例,减少不必要的组件重新初始化:

dataSource: MatTableDataSource<Data> = new MatTableDataSource();

constructor(private serviceFetch: ServiceFetch) {}

onClickSearchRmsTradesData(): void {
  this.serviceFetch.fetchRecords().subscribe((res: Data[]) => {
    // 直接更新data属性,而非创建新的MatTableDataSource实例
    this.dataSource.data = res;
  });
}

关键说明

  • ngAfterViewInit是获取@ViewChild实例的正确时机,此时DOM已完全初始化
  • 通过OnChanges监听输入属性变化,确保父组件更新数据源后子组件能同步绑定分页器
  • 分页器的length必须与实际数据长度关联,否则分页按钮状态会异常

内容的提问来源于stack exchange,提问作者Kashmira

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 17:22:13