如何让Angular+Material表格的总计行排序时始终固定在底部
解决Angular Material表格总计行始终固定在底部的问题
方法一:使用Angular Material原生页脚行(推荐)
不要把总计行混入表格的数据源,而是利用MatTable的mat-footer-row特性单独实现总计行,这样天然不受排序影响,始终固定在表格底部。
步骤如下:
- 在组件类中分开维护数据行和总计数据:
// 普通数据行 dataRows = [ { name: 'Alice', value1: 1, value2: 2 }, { name: 'Bob', value1: 2, value2: 4 }, { name: 'Carl', value1: 3, value2: 1 } ]; // 总计数据 totalRow = { name: 'TOTAL', value1: 6, value2: 7 };
- 在模板中配置表格的页脚行定义,并渲染总计行:
<mat-table [dataSource]="dataRows" matSort> <!-- name列 --> <ng-container matColumnDef="name"> <mat-header-cell *matHeaderCellDef mat-sort-header>名称</mat-header-cell> <mat-cell *matCellDef="let row">{{ row.name }}</mat-cell> <!-- 页脚单元格 --> <mat-footer-cell *matFooterCellDef>{{ totalRow.name }}</mat-footer-cell> </ng-container> <!-- value1列 --> <ng-container matColumnDef="value1"> <mat-header-cell *matHeaderCellDef mat-sort-header>数值1</mat-header-cell> <mat-cell *matCellDef="let row">{{ row.value1 }}</mat-cell> <mat-footer-cell *matFooterCellDef>{{ totalRow.value1 }}</mat-footer-cell> </ng-container> <!-- value2列 --> <ng-container matColumnDef="value2"> <mat-header-cell *matHeaderCellDef mat-sort-header>数值2</mat-header-cell> <mat-cell *matCellDef="let row">{{ row.value2 }}</mat-cell> <mat-footer-cell *matFooterCellDef>{{ totalRow.value2 }}</mat-footer-cell> </ng-container> <!-- 渲染表头、数据行、页脚行 --> <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row> <mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row> <mat-footer-row *matFooterRowDef="displayedColumns"></mat-footer-row> </mat-table>
这种方式完全遵循Angular Material的设计规范,不需要额外处理排序逻辑,是最简洁可靠的方案。
方法二:重写数据源的排序逻辑(若必须将总计行混入数据源)
如果因为特殊需求必须把总计行放在数据源数组中,可以重写MatTableDataSource的sortData方法,确保排序后总计行始终追加在最后。
示例代码:
import { MatTableDataSource, MatSort } from '@angular/material/table'; // 定义数据类型 interface TableRow { name: string; value1: number; value2: number; } @Component({ /* ... */ }) export class YourComponent { displayedColumns = ['name', 'value1', 'value2']; dataSource = new MatTableDataSource<TableRow>([ { name: 'Alice', value1: 1, value2: 2 }, { name: 'Bob', value1: 2, value2: 4 }, { name: 'Carl', value1: 3, value2: 1 }, { name: 'TOTAL', value1: 6, value2: 7 } ]); ngOnInit() { // 重写排序逻辑 const originalSortData = this.dataSource.sortData; this.dataSource.sortData = (data: TableRow[], sort: MatSort) => { // 分离总计行和普通数据行 const totalRow = data.find(row => row.name === 'TOTAL'); const regularRows = data.filter(row => row.name !== 'TOTAL'); // 用原生逻辑排序普通行 const sortedRegularRows = originalSortData.call(this.dataSource, regularRows, sort); // 将总计行追加到排序后的数组末尾 return totalRow ? [...sortedRegularRows, totalRow] : sortedRegularRows; }; } }
为什么之前的方法无效?
你之前返回'ZZZZZZZZ'的方式,本质是利用字符串排序规则:升序时'ZZZZZZZZ'是最大的字符串,会排在最后;但降序时,字符串排序会把最大的值放在最前面,所以总计行就跑到了顶部。这种方式无法同时适配升序和降序两种排序方向,因此不可行。
内容的提问来源于stack exchange,提问作者deanWombourne
相关产品推荐
相关产品推荐

