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

Angular 18 Material动态表格分页失效问题求助

Angular 18 + Angular Material 动态表格分页失效问题(含无数据模板时)

问题描述

使用Angular 18和Angular Material开发动态表格组件,父组件传入JSON数据后渲染表格,但包含无数据提示模板时分页功能完全失效;移除无数据模板后分页恢复正常。

核心原因

外层*ngIf="dataSource.data.length > 0"会在数据为空时,将包含表格和分页器的整个<div>从DOM中移除。此时@ViewChild(MatPaginator)获取的引用会变为undefined。当后续数据传入时,*ngIf重新渲染DOM,但connectPaginator方法可能在分页器组件还未完成初始化时就执行,导致无法正确绑定分页器到数据源。

解决方案

方案一:调整DOM结构,保持分页器始终存在(推荐)

将*ngIf的作用范围缩小到表格本身,让分页器始终保留在DOM中(无数据时自动隐藏),避免分页器引用丢失。

修改后的component.html:

<div class="mat-elevation-z8 preview-container">
  <!-- 仅在有数据时显示表格 -->
  <table *ngIf="dataSource.data.length > 0" mat-table [dataSource]="dataSource" class="mat-table">
    <ng-container *ngFor="let column of displayedColumns" [matColumnDef]="column">
      <th mat-header-cell *matHeaderCellDef> {{ column }} </th>
      <td mat-cell *matCellDef="let element"> {{ element[column] }} </td>
    </ng-container>

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

  <!-- 分页器随表格显示/隐藏,始终存在于DOM中 -->
  <mat-paginator *ngIf="dataSource.data.length > 0" [pageSizeOptions]="[10, 20]" showFirstLastButtons></mat-paginator>

  <!-- 无数据提示 -->
  <div *ngIf="dataSource.data.length === 0" class="no-data-message-container">
    <p class="no-data-message">暂无数据!</p>
  </div>
</div>

方案二:用ViewChildren监听分页器变化

改用@ViewChildren监听分页器的DOM变化,确保每次分页器初始化完成后再绑定到数据源。

修改后的component.ts:

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

export class PreviewComponent implements OnChanges, AfterViewInit, OnInit {
  @Input() data: any[] = [];
  displayedColumns: string[] = [];
  dataSource: MatTableDataSource<any> = new MatTableDataSource();

  @ViewChildren(MatPaginator) paginators!: QueryList<MatPaginator>;

  ngOnInit(): void {}

  ngOnChanges(): void {
    if (this.data.length > 0) {
      this.displayedColumns = Object.keys(this.data[0]);
      this.dataSource.data = this.data;
    } else {
      this.dataSource.data = [];
    }
    
    this.connectPaginator();
  }

  ngAfterViewInit(): void {
    // 监听分页器列表变化,确保DOM更新后重新绑定
    this.paginators.changes.subscribe(() => {
      this.connectPaginator();
    });
    this.connectPaginator();
  }

  connectPaginator() {
    const paginator = this.paginators.first;
    if (this.dataSource && paginator) {
      this.dataSource.paginator = paginator;
    }
  }
}

方案三:延迟绑定分页器(临时修复)

通过setTimeout延迟执行绑定逻辑,确保DOM已完成渲染。

修改connectPaginator方法:

connectPaginator() {
  setTimeout(() => {
    if (this.dataSource && this.paginator) {
      this.dataSource.paginator = this.paginator;
    }
  }, 0);
}

方案对比

  • 方案一:逻辑简单,从根源避免引用丢失,是最稳定的解决方案。
  • 方案二:适合复杂动态渲染场景,监听DOM变化确保绑定时机准确。
  • 方案三:快速临时修复,但依赖浏览器事件循环,不推荐长期使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 23:00:58