Angular mat-table: 是否可以按列合并单元格?
Angular mat-table: Is it possible to merge cells by columns?
我无法找到有关如何在 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 列中的单元格。
您想 "make the cells in columns Block and Block Size to merge."...没有字段 'Block Size',所以我假设您的意思是 'Lot Size' 与 'Block ID' 合并。
为此我们创建一个任意列名'mergedField'(在TS中)然后一起打印出{{element.block_id}}{{element.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_id}}{{element.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>
与此同时,您可能找到了解决问题的方法,但由于我刚刚创建了以下 StackBlitz
,我将其分享以防其他人寻找相同问题的解决方案。
https://stackblitz.com/edit/angular-gevqvq
The RowSpanComputer
class from this solution is based on code found in the open source project Koia. In there, the computed rowspan
attributes are used within summary-table.component.html
.
更新
上面链接的 StackBlitz 中的代码示例仅适用于乐观情况。理想情况下,不会为最后 table 列计算行跨度,否则如果行与前一列相同,则不会显示这些行。
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,看看它是如何工作的。
我无法找到有关如何在 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 列中的单元格。
您想 "make the cells in columns Block and Block Size to merge."...没有字段 'Block Size',所以我假设您的意思是 'Lot Size' 与 'Block ID' 合并。
为此我们创建一个任意列名'mergedField'(在TS中)然后一起打印出{{element.block_id}}{{element.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_id}}{{element.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>
与此同时,您可能找到了解决问题的方法,但由于我刚刚创建了以下 StackBlitz
,我将其分享以防其他人寻找相同问题的解决方案。
https://stackblitz.com/edit/angular-gevqvq
The
RowSpanComputer
class from this solution is based on code found in the open source project Koia. In there, the computedrowspan
attributes are used withinsummary-table.component.html
.
更新
上面链接的 StackBlitz 中的代码示例仅适用于乐观情况。理想情况下,不会为最后 table 列计算行跨度,否则如果行与前一列相同,则不会显示这些行。
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,看看它是如何工作的。