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

如何在Angular组件与Material Design模板间传递对象列表

Angular Material表格无法渲染接口返回的分页数据问题

我在Angular组件中实现了getReports方法,该方法订阅接口后返回包含对象列表的分页数据(控制台打印可见),希望在Material Design构建的HTML表格模板中展示每个报告的from、until、issi、status等字段,但数据似乎未正确从组件传递到HTML模板。相关代码与数据如下:

接口返回数据

{"content": [{"id": 1,"from": "2022-03-14T23:00:00","until": "2022-03-15T13:37:00","issi": "1500","format": "KML","creationDate": "2023-01-19T11:53:40.018808","status": "DOWNLOADABLE"},{"id": 2,"from": "2022-03-14T23:00:00","until": "2022-03-15T13:37:00","issi": "1500","format": "KML","creationDate": "2023-01-19T11:54:23.810516","status": "DOWNLOADABLE"},{"id": 3,"from": "2022-03-14T23:00:00","until": "2022-03-15T13:37:00","issi": "1500","format": "CSV","creationDate": "2023-01-19T11:55:24.018175","status": "DOWNLOADABLE"}],"pageable": {"sort": {"empty": false,"sorted": true,"unsorted": false},"offset": 0,"pageNumber": 0,"pageSize": 25,"unpaged": false,"paged": true},"totalPages": 1,"totalElements": 12,"last": true,"size": 25,"number": 0,"sort": {"empty": false,"sorted": true,"unsorted": false},"first": true,"numberOfElements": 12,"empty": false}

组件代码

import {Component, ViewChild, AfterViewInit, Input} from '@angular/core';
import {MatPaginator} from '@angular/material/paginator';
import {ReportInterface} from "../../types/ReportInterface";
import {MatTableDataSource} from "@angular/material/table";
import {ReportsService} from "../../services/reports.service";
import {saveAs} from "file-saver";

@Component({
  selector: 'app-reports-table',
  templateUrl: './reports-table.component.html',
  styleUrls: ['./reports-table.component.scss']
})
export class ReportsTableComponent implements AfterViewInit {
  public displayedColumns: string[] = ['createdAt', 'from', 'until', 'devices', 'status', 'action'];
  @Input() data: ReportInterface[] = [];
  dataSource!: MatTableDataSource<any>;
  // @ViewChild(MatPaginator) paginator: MatPaginator;

  constructor(private reportsService: ReportsService) { }

  ngOnInit(): void {
    this.getReports();
  }

  ngAfterViewInit(): void {
    // this.dataSource.paginator = this.paginator;
  }

  downloadReport(id: number, format: 'CSV' | 'KML') {
    this.reportsService.downloadReport(id).subscribe((buffer) => {
      const data: Blob = new Blob([buffer], {
        type: "text/csv;charset=utf-8"
      });

      if (format === 'CSV') {
       return  saveAs(data, "report-" + id + ".csv");
      }

      return saveAs(data, "report-" + id + ".kml");
    });
  }

  getReports() {
    this.reportsService.getAllReports().subscribe({
      next: (element:ReportInterface[]) => {
        this.dataSource = new MatTableDataSource(element);
        console.log('aco',element);
      },
      error: (err) => {
        alert('Error while fetching users');
      },
    });
  }
}

HTML模板代码

<table mat-table [dataSource]="dataSource" class="reports-table">


  <!-- Create at Column -->
  <ng-container matColumnDef="createdAt">
    <th mat-header-cell *matHeaderCellDef> Created at </th>
    <td mat-cell *matCellDef="let element"> {{element.creationDate | date: 'd/M/yy - H:mm'}} </td>
  </ng-container>

  <!-- From Column -->
  <ng-container matColumnDef="from">
    <th mat-header-cell *matHeaderCellDef> From </th>
    <td mat-cell *matCellDef="let element"> {{element.from | date: 'd/M/yy - H:mm'}} </td>
  </ng-container>

  <!-- Until Column -->
  <ng-container matColumnDef="until">
    <th mat-header-cell *matHeaderCellDef> To </th>
    <td mat-cell *matCellDef="let element"> {{element.until | date: 'd/M/yy - H:mm'}} </td>
  </ng-container>

  <!-- Status Column -->
  <ng-container matColumnDef="status">
    <th mat-header-cell *matHeaderCellDef> Status </th>
    <td mat-cell *matCellDef="let element"> {{element.status.toLowerCase()}} </td>
  </ng-container>

  <!-- Devices Column -->
  <ng-container matColumnDef="devices">
    <th mat-header-cell *matHeaderCellDef> Devices </th>
    <td mat-cell *matCellDef="let element"> {{element.issi}} </td>
  </ng-container>

  <!-- Actions Column -->
  <ng-container matColumnDef="action">
    <th mat-header-cell *matHeaderCellDef> Action </th>
    <td mat-cell *matCellDef="let element">
      <button mat-button class="download-button" (click)="downloadReport(element.id, element.format)">Download in {{element.format}}</button>
    </td>
  </ng-container>

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

  <mat-paginator [pageSizeOptions]="[5, 10, 20]"
                 showFirstLastButtons
                 aria-label="Select page of periodic elements">
  </mat-paginator>
</table>

问题分析与解决方案

核心问题

接口返回的是分页结构数据,实际的报告列表存储在content字段中,但组件代码直接把整个响应对象传给了MatTableDataSource,而非提取content数组。此外还有两个次要问题:

  • 组件未实现OnInit接口,ngOnInit可能无法正常触发
  • 分页器未正确绑定到数据源

修复步骤

  1. 修正接口响应处理
    在getReports方法中,提取响应里的content字段作为表格数据源:

    getReports() {
      this.reportsService.getAllReports().subscribe({
        next: (response) => {
          // 提取content数组作为数据源
          this.dataSource = new MatTableDataSource(response.content);
          // 绑定分页器
          this.dataSource.paginator = this.paginator;
          console.log('aco', response.content);
        },
        error: (err) => {
          alert('Error while fetching reports');
        },
      });
    }
    
  2. 实现OnInit接口
    修改组件类定义,添加OnInit接口:

    export class ReportsTableComponent implements OnInit, AfterViewInit {
      // ... 其他代码
    }
    
  3. 启用分页器绑定
    取消注释@ViewChild和ngAfterViewInit中的代码:

    @ViewChild(MatPaginator) paginator!: MatPaginator;
    
    ngAfterViewInit(): void {
      if (this.dataSource) {
        this.dataSource.paginator = this.paginator;
      }
    }
    

    也可直接在数据加载完成后绑定分页器(如步骤1所示),避免异步加载导致的分页器未初始化问题。

  4. 可选:类型定义优化
    定义分页响应类型,让代码更严谨:

    export interface PageResponse<T> {
      content: T[];
      pageable: any;
      totalPages: number;
      totalElements: number;
      // 其他分页相关字段
    }
    

    订阅时指定类型:

    next: (response: PageResponse<ReportInterface>) => {
      // ...
    }
    

验证修复

完成修改后重新运行项目,表格将正确渲染content中的报告数据,分页器也能正常工作。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 14:01:18