Angular mat-table: Is it possible to merge cells by columns?
Meanwhile you probably found a solution to your problem but since I just created the following StackBlitz
, I share it in case someone else looks for a solution to the same issue.
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
.
UPDATE
The code example in the above linked StackBlitz works only for optimistic cases. Ideally no row spans are computed for the last table column, otherwise rows are not displayed if they are identical to the previous one.
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);
}
In the HTML template this must also be taken into account. There we treat the preceding and the last column differently.
<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>
Please take a look at this improved StackBlitz and see how it works.
simple guy
As a programmer I am still a newbie and that is why I created this account. ^^ In general, I am simple guy with simple wants and needs. But when I really want something I go and work for it.
Updated on June 07, 2022Comments
-
simple guy almost 2 years
I'm having trouble finding an answer on how to merge columns cells in mat-table. Only saw few examples in merging row cells using
when
. So was wondering if i can find answers here.I have this JSON data:
{ "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 } ] }
And was expecting an output in mat-table as:
+------------------------------------------------------------------+ | 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 | +------------------------------------------------------------------+
As you can see I want to make the cells in columns Block and Block Size to merge.
-
simple guy almost 5 yearssorry, not what i was looking for. i want to merge cell horizontally not vertically.
-
shahnshah over 3 yearsAmazing!!! this saved a ton of work for me, thanks a million
-
robs23 over 3 yearsThanks for it, works like a charm. I noticed, though, that it works correctly for first 3 columns, all further columns get spanColumnContext.spannnedRow = undefined. Perhaps you know why this is?
-
uminder over 3 years@robs23: I had a look at the code I posted and noticed there was a problem. I updated/improved my answer accordingly.
-
robs23 over 3 yearsYou probably were targetting some other edge case, for me things didn't change a bit - it still doesn't work. I forked your example on stackblitz.com/edit/angular-table-row-span-gn6rnu?file=src/app/… . If you have a chance, please check it out, I changed your data to the exact data I work with and no rows are merged
-
uminder over 3 years@robs23: The
RowSpanComputer
class computes therowspan
for each cell out of the specified table data (array of rows). It basically loops over the rows and increments therowspan
for cells as long as their value remains unchanged and left located cells were also spanned. As soon as the value changes, the correspondingrowspan
is reset to zero. I took a quick look to your code and see that the values in the first few columns are different for each row. Therefore norowspan
is applied at all. If you need a solution for your particular case, please post a new question. -
robs23 over 3 yearsThanks. What I didn't catch was the fact that you have to provide columns ordered by rowspan descending.. I mean, If first column does not contain repeatable data (all values are unique in first column for all rows), rowspan will always be 1 for all next columns, regardless if there are any repeatable values there or not.. If I feed your function with column names in appropriate order, it will count rowspan correctly. And I can reorder them the way I want in the template anyway