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
相关产品推荐
相关产品推荐

