本文已参与「新人创作礼」活动,一起开启掘金创作之路。
三个月前
三个月前遇到了表格需要在表尾设置一个冻结行显示合计的需求,通过翻阅文档,当时的写法是这样的:(所有说明和介绍均留在下方《正确用法》中)
网页部分:
<table
mat-table
class="tableData"
[dataSource]="skuData"
matSort
matSortDisableClear matSortDirection="asc"
[@animateStagger]="{value:'50'}">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef>序号</th>
<td mat-cell *matCellDef="let row">{{ row.no }}</td>
<td mat-footer-cell *matFooterCellDef> 合计 </td>
</ng-container>
……
<ng-container matColumnDef="total_weight">
<th mat-header-cell *matHeaderCellDef>产品总重</th>
<td mat-cell *matCellDef="let row">{{ row.total_weight | number:"0.2" }}</td>
<td mat-footer-cell *matFooterCellDef> {{ getTotalTotalWeight() | number:"0.2" }} </td>
</ng-container>
<!-- 表尾 -->
<tr mat-header-row *matHeaderRowDef="skuDataColumns; sticky:true"></tr>
<tr mat-row *matRowDef="let row; columns: skuDataColumns;" class="product" matRipple></tr>
<tr mat-footer-row *matFooterRowDef="skuDataColumns"></tr>
</table>
ts部分:
getTotalPlanQty(): number {
return this.general.getTotal(this.skuData, 'plan_qty')
}
getTotalFactQty() {
return this.general.getTotal(this.skuData, 'fact_qty')
}
getTotalPlanWeight() {
return this.general.getTotal(this.skuData, 'plan_weight')
}
getTotalTotalWeight() {
return this.general.getTotal(this.skuData, 'total_weight')
}
由于只有四列求和,当时第一次用也没觉得有什么问题。
直到我今天碰到一个需要求和五列合计的表格,发现原来的写法也太过繁杂了,于是稍微重构优化一下,顺便总结一下正确用法。
正确用法
ts部分
获取表格的数据:
fetchTableInfo(): void {
const url = `transport/detail/${this.planId}`;
this.confSvc.sendGetCatch(url, this.isLoading).subscribe(res => {
// 表格数据
this.skuData = res['data'].sku_data || [];
this.confSvc.changeLoading(false);
});
}
分析数据结构:(以下均为测试数据)
skuData=[
{
"other_price": "0.00",
"tax_price": "0.00",
"first_freight_price": "0.00",
……
"plan_weight": "0",
"plan_total_weight": "0",
"no": 1
},
{
"other_price": "0.00",
"tax_price": "0.00",
"first_freight_price": "0.00",
……
"plan_weight": "0",
"plan_total_weight": "0",
"no": 2
}
]
求和公共函数
其中Array为数据数组,key为数组中对应的数据字段
该数组的作用为:根据key值对数组Array中为字段为key的值进行求和并返回
// 放入数组,及数组对应的键值
getTotal(Array, key: string): number {
// 初始化总和
let tempOrderQty = 0;
// 循环求值
Array.forEach(value => {
tempOrderQty += toInteger(value[key]);
});
// 返回总值
return tempOrderQty;
}
求和时调用:
getTotalQty(Index: string): number {
return this.general.getTotal(this.skuData, Index);
}
html部分
<table
mat-table
class="tableData"
[dataSource]="skuData"
matSort matSortDisableClear
matSortDirection="asc"
[@animateStagger]="{value:'50'}">
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef>序号</th>
<td mat-cell *matCellDef="let row">{{ row.no }}</td>
<td mat-footer-cell *matFooterCellDef>合计</td>
</ng-container>
……
<ng-container matColumnDef="product_total_price">
<th mat-header-cell *matHeaderCellDef>产品总价</th>
<td mat-cell *matCellDef="let row">{{ row.product_total_price }}</td>
<td mat-footer-cell *matFooterCellDef> {{ getTotalQty('product_total_price') | number:"0.0-2" }} </td>
</ng-container>
<ng-container matColumnDef="other_price">
<th mat-header-cell *matHeaderCellDef>其他费用单价</th>
<td mat-cell *matCellDef="let row">{{ row.other_price }}</td>
<td mat-footer-cell *matFooterCellDef>-</td>
</ng-container>
<!-- 表尾 -->
<tr mat-header-row *matHeaderRowDef="skuDataColumns; sticky:true"></tr>
<tr mat-row *matRowDef="let row; columns: skuDataColumns;" class="product" matRipple></tr>
<tr mat-footer-row *matFooterRowDef="skuDataColumns"></tr>
</table>
注意即使不求和,该列的ng-container内也需要加上(此处用-代替,也可以为空)
<td mat-footer-cell *matFooterCellDef>-</td>
求和列的ng-container部分则需要加上
<td mat-footer-cell *matFooterCellDef> {{ getTotalQty('product_total_price') | number:"0.0-2" }} </td>
其中getTotalQty为求和函数,参数'product_total_price'为数组中需要求和的字段名称
注意不要写成row.product_total_price的格式,因为row.product_total_price会传具体的数值
| number:"0.0-2" 为number管道,用于设置数字的显示 ,用法如下
number管道用来将数字处理为需要的小数格式
接收的参数格式为:{最少整数位数}.{最少小数位数}-{最多小数位数}
- 其中最少整数位数默认为1
- 最少小数位数默认为0
- 最多小数位数默认为3
- 当小数位数少于规定的{最少小数位数}时,会自动补0
- 当小数位数多于规定的{最多小数位数}时,会四舍五入
最后在表尾加上
<tr mat-footer-row *matFooterRowDef="skuDataColumns"></tr>
<!-- skuDataColumns为行模板定义 -->
代码看着舒服多了!收工!