Angular mat-table:是不是可以按列合并单元格?
Posted
技术标签:
【中文标题】Angular mat-table:是不是可以按列合并单元格?【英文标题】:Angular mat-table: Is it possible to merge cells by columns?Angular mat-table:是否可以按列合并单元格? 【发布时间】:2019-11-14 21:21:14 【问题描述】:我无法找到有关如何在 mat-table 中合并列单元格的答案。在使用when
合并行单元格时只看到了几个例子。所以想知道我是否可以在这里找到答案。
我有这个 JSON 数据:
"id": 4,
"description": "this is another block",
"block_size": 3480,
"lot_count": 5,
"lots": [
"id": 17,
"lot_name": "test 17",
"status": "SOLD",
"block_id": 4,
"lot_id": 1,
"lot_size": 828
,
"id": 18,
"lot_name": "test 18",
"status": "OPEN",
"block_id": 4,
"lot_id": 2,
"lot_size": 885
,
"id": 19,
"lot_name": "test 19",
"status": "SOLD",
"block_id": 4,
"lot_id": 3,
"lot_size": 648
,
"id": 20,
"lot_name": "test 20",
"status": "OPEN",
"block_id": 4,
"lot_id": 4,
"lot_size": 553
,
"id": 21,
"lot_name": "Test 21",
"status": "OPEN",
"block_id": 4,
"lot_id": 5,
"lot_size": 566
]
并且期望 mat-table 中的输出为:
+------------------------------------------------------------------+
| No. Lot Name Block Block Size Lot Id Lot Size |
+------------------------------------------------------------------+
| 17 test 17 1 828 |
| 18 test 18 2 885 |
| 19 test 19 4 3480 3 648 |
| 20 test 20 4 553 |
| 21 test 21 5 566 |
+------------------------------------------------------------------+
如您所见,我想让 Block 和 Block Size 列中的单元格合并。
【问题讨论】:
【参考方案1】:与此同时,您可能找到了解决问题的方法,但由于我刚刚创建了以下 StackBlitz
,因此我分享它以防其他人寻找相同问题的解决方案。
https://stackblitz.com/edit/angular-gevqvq
此解决方案中的
RowSpanComputer
类基于开源项目Koia 中的代码。在那里,计算出的rowspan
属性在summary-table.component.html
中使用。
更新
上面链接的 StackBlitz 中的代码示例仅适用于乐观情况。理想情况下,不会为表的最后一列计算行跨度,否则如果行与前一列相同,则不会显示行。
ngOnInit()
this.columnNames = Object.keys(this.data[0]);
this.lastColumnName = this.columnNames[this.columnNames.length - 1];
this.allButLastColumnNames = this.columnNames.slice(0, -1);
this.rowSpans = this.rowSpanComputer.compute(this.data, this.allButLastColumnNames);
在 HTML 模板中也必须考虑到这一点。在那里我们区别对待前一列和最后一列。
<table mat-table *ngIf="rowSpans" [dataSource]="data" class="mat-elevation-z8">
<ng-container *ngFor="let columnName of allButLastColumnNames; let iCol = index" [matColumnDef]="columnName">
<th mat-header-cell *matHeaderCellDef> columnName </th>
<td mat-cell *matCellDef="let row; let iRow = index" [attr.rowspan]="rowSpans[iCol][iRow].span"
[style.display]="rowSpans[iCol][iRow].span === 0 ? 'none' : ''"> row[columnName] </td>
</ng-container>
<ng-container [matColumnDef]="lastColumnName">
<th mat-header-cell *matHeaderCellDef> lastColumnName </th>
<td mat-cell *matCellDef="let row; let iRow = index"> row[lastColumnName] </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnNames"></tr>
<tr mat-row *matRowDef="let row; columns: columnNames"></tr>
</table>
请看看这个改进的StackBlitz,看看它是如何工作的。
【讨论】:
太棒了!!!这为我节省了大量工作,谢谢一百万 感谢它,就像一个魅力。不过,我注意到它对前 3 列正常工作,所有其他列都得到 spanColumnContext.spannnedRow = undefined。也许你知道这是为什么? @robs23:我查看了我发布的代码,发现有问题。我相应地更新/改进了我的答案。 您可能针对的是其他一些极端情况,对我来说,事情并没有改变——它仍然不起作用。我在 stackblitz.com/edit/angular-table-row-span-gn6rnu?file=src/app/… 上分叉了你的例子。如果您有机会,请检查一下,我将您的数据更改为我使用的确切数据,并且没有合并任何行 @robs23:RowSpanComputer
类为指定表数据(行数组)中的每个单元格计算 rowspan
。它基本上循环遍历行并增加单元格的rowspan
,只要它们的值保持不变并且左侧的单元格也被跨越。一旦值发生变化,对应的rowspan
就会重置为零。我快速查看了您的代码,发现前几列中的值对于每一行都不同。因此根本没有应用rowspan
。如果您需要针对特定案例的解决方案,请发布一个新问题。【参考方案2】:
您想“使块和块大小列中的单元格合并。”...没有“块大小”字段,所以我假设您的意思是“批量大小”与“块 ID”合并。
为此,我们创建一个任意列名称“mergedField”(在 TS 中),然后一起打印出 element.block_idelement.lot_size
(在 HTML 中)
相关TS:
import Component from '@angular/core';
import AppService from './app.service'
@Component(
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
)
export class AppComponent
name = 'Angular';
displayedColumns: string[] = ['id', 'lot_name', 'block_id', 'mergedField', 'lot_id', 'lot_size', 'status'];
dataSource;
myJSONData: any[] = [];
constructor(private userService: AppService)
ngOnInit()
let someVar = this.userService.getJSON();
this.myJSONData = someVar.lots;
console.log(this.myJSONData);
this.dataSource = this.myJSONData;
相关HTML:
<table mat-table [dataSource]="dataSource" class="mat-elevation-z8">
<!--- Note that these columns can be defined in any order.
The actual rendered columns are set as a property on the row definition" -->
<!-- id Column -->
<ng-container matColumnDef="id">
<th mat-header-cell *matHeaderCellDef> No </th>
<td mat-cell *matCellDef="let element"> element.id </td>
</ng-container>
<!-- block_id Column -->
<ng-container matColumnDef="block_id">
<th mat-header-cell *matHeaderCellDef> Block </th>
<td mat-cell *matCellDef="let element"> element.block_id </td>
</ng-container>
<!-- block_id Column -->
<ng-container matColumnDef="mergedField">
<th mat-header-cell *matHeaderCellDef> Block Size (merged) </th>
<td mat-cell *matCellDef="let element"> element.block_idelement.lot_size </td>
</ng-container>
<!-- lot_id Column -->
<ng-container matColumnDef="lot_id">
<th mat-header-cell *matHeaderCellDef> Lot ID </th>
<td mat-cell *matCellDef="let element"> element.lot_id </td>
</ng-container>
<!-- lot_name Column -->
<ng-container matColumnDef="lot_name">
<th mat-header-cell *matHeaderCellDef> Lot Name </th>
<td mat-cell *matCellDef="let element"> element.lot_name </td>
</ng-container>
<!-- lot_size Column -->
<ng-container matColumnDef="lot_size">
<th mat-header-cell *matHeaderCellDef> Lot Size </th>
<td mat-cell *matCellDef="let element"> element.lot_size </td>
</ng-container>
<!-- status Column -->
<ng-container matColumnDef="status">
<th mat-header-cell *matHeaderCellDef> Status </th>
<td mat-cell *matCellDef="let element"> element.status </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
完成working stackblitz here
【讨论】:
对不起,不是我想要的。我想水平合并单元格而不是垂直合并。以上是关于Angular mat-table:是不是可以按列合并单元格?的主要内容,如果未能解决你的问题,请参考以下文章
Angular Material mat-table 在组件中定义可重用列
在 mat-table 的 mat-cell 内实现 if else 条件 - Angular 5
为啥“width: auto”属性对 Angular mat-table 元素没有影响?
Angular Material 2:多个 mat-table 排序仅适用于第一个表