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

Angular Material固定表头表脚表格:如何在页脚显示行数据总和

Got it, let's figure out how to add those row totals to your Angular Material Table footer—since you're using pagination, we'll cover both current page totals and totals for all filtered data, depending on what you need. Here's a step-by-step solution that fits right into your existing code:

1. Add Total Calculation Logic to Your Component

First, we'll create methods in your component class to calculate the sums. We'll handle two scenarios: totals for the current page (since you have a paginator) and totals for all filtered data (if you want to show the grand total regardless of pagination).

Add these methods to your component:

import { ViewChild, AfterViewInit } from '@angular/core';
import { MatPaginator } from '@angular/material/paginator';
import { MatTableDataSource } from '@angular/material/table';

// Make sure your component implements AfterViewInit to link the paginator
export class YourPurchaseComponent implements AfterViewInit {
  @ViewChild('paginator') paginator!: MatPaginator;
  dataSource = new MatTableDataSource<any>(); // Replace `any` with your actual purchase data type

  // Calculate total quantity for the CURRENT page
  getCurrentPageTotalQuantity(): number {
    if (!this.dataSource.paginator) return 0;
    const startIdx = this.dataSource.paginator.pageIndex * this.dataSource.paginator.pageSize;
    const endIdx = startIdx + this.dataSource.paginator.pageSize;
    const currentPageData = this.dataSource.filteredData.slice(startIdx, endIdx);
    return currentPageData.reduce((sum, purchase) => sum + purchase.quantity, 0);
  }

  // Calculate total price for the CURRENT page
  getCurrentPageTotalPrice(): number {
    if (!this.dataSource.paginator) return 0;
    const startIdx = this.dataSource.paginator.pageIndex * this.dataSource.paginator.pageSize;
    const endIdx = startIdx + this.dataSource.paginator.pageSize;
    const currentPageData = this.dataSource.filteredData.slice(startIdx, endIdx);
    return currentPageData.reduce((sum, purchase) => sum + purchase.price, 0);
  }

  // Optional: Calculate total quantity for ALL filtered data (grand total)
  getGrandTotalQuantity(): number {
    return this.dataSource.filteredData.reduce((sum, purchase) => sum + purchase.quantity, 0);
  }

  // Optional: Calculate total price for ALL filtered data (grand total)
  getGrandTotalPrice(): number {
    return this.dataSource.filteredData.reduce((sum, purchase) => sum + purchase.price, 0);
  }

  ngAfterViewInit() {
    // Link the paginator to your data source (critical for page-based calculations)
    this.dataSource.paginator = this.paginator;
  }

  // Your existing methods (editPurchase, exportCsv, etc.)...
}

Now, modify your table's footer cells to display the calculated totals. We'll keep the same fxHide/fxShow.gt-sm logic as your headers and cells to maintain consistency across screen sizes, and add some styling to make the totals stand out.

Update your quantity and price column definitions:

<!-- Quantity Column with Footer Total -->
<ng-container matColumnDef="quantity">
  <mat-header-cell *matHeaderCellDef fxHide fxShow.gt-sm mat-sort-header>Quantity</mat-header-cell>
  <mat-cell *matCellDef="let purchase" fxHide fxShow.gt-sm>
    <p class="font-weight-600 text-truncate"> {{purchase.quantity}} </p>
  </mat-cell>
  <mat-footer-cell *matFooterCellDef fxHide fxShow.gt-sm>
    <p class="font-weight-bold">Total: {{getCurrentPageTotalQuantity()}}</p>
    <!-- Replace with getGrandTotalQuantity() if you want the grand total -->
  </mat-footer-cell>
</ng-container>

<!-- Price Column with Footer Total -->
<ng-container matColumnDef="price">
  <mat-header-cell *matHeaderCellDef fxHide fxShow.gt-sm mat-sort-header>Price</mat-header-cell>
  <mat-cell *matCellDef="let purchase" fxHide fxShow.gt-sm>
    <p class="font-weight-600 text-truncate"> {{purchase.price}} </p>
  </mat-cell>
  <mat-footer-cell *matFooterCellDef fxHide fxShow.gt-sm>
    <p class="font-weight-bold">Total: {{getCurrentPageTotalPrice() | currency}}</p>
    <!-- Use getGrandTotalPrice() for grand total; the currency pipe formats the price nicely -->
  </mat-footer-cell>
</ng-container>

<!-- Keep your existing header, row, and footer row definitions as-is -->
<mat-header-row *matHeaderRowDef="displayedColumns; sticky:true"></mat-header-row>
<mat-row *matRowDef="let purchase; columns: displayedColumns;" class="contact" (click)="editPurchase(purchase)" [ngClass]="{'accent-50':checkboxes[purchase._id]}" matRipple [@animate]="{value:'*',params:{y:'100%'}}">
</mat-row>
<mat-footer-row mat-footer-row *matFooterRowDef="displayedColumns; sticky: true"></mat-footer-row>

<mat-toolbar>
  <mat-toolbar-row>
    <mat-icon (click)="exportCsv(dataSource)" title="Export as CSV">save_alt</mat-icon>
    <mat-paginator #paginator [length]="dataSource.filteredData.length" [pageIndex]="0" [pageSize]="10" [pageSizeOptions]="[5, 10, 25, 100]" showFirstLastButtons>
    </mat-paginator>
  </mat-toolbar-row>
</mat-toolbar>

3. Notes for Edge Cases

  • Filtering/Sorting: The totals will automatically update when you filter or sort the table because we're using filteredData, which reflects the current set of visible (filtered/sorted) data.
  • Async Data: If your data loads asynchronously (e.g., from an API), make sure you set this.dataSource.data = yourPurchaseData after the data is fetched—this will trigger the total calculations to update.
  • Null/Undefined Values: If quantity or price can be null, add a check in the reduce function to avoid NaN, like sum + (purchase.quantity || 0).

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:48:12