There is a sample of data table which consists of multiple header rows
| | Song 1 | Song 2 | Song 3 | |---------------------------|----------------|----------------| | Artist | Perc % | Val $ | Perc % | Val $ | Perc % | Val $ | |-------------------------------------------------------------| | Q1 | 10% | 200$ | 15% | 250$ | | | | BW | 10% | 200$ | 10% | 200$ | | | | POD | 5% | 150$ | 10$ | 200$ | | | | | | | | | | | | SUM | 25% | 550$ | 25% | 650$ | | |
with provided dataset
{
"data": [{
"artistId": "A001",
"artistName": "Q1",
"songs": [{
"songId": "S001",
"songName": "Song 1",
"percentage": "10%",
"value": "$200"
},
{
"songId": "S002",
"songName": "Song 2",
"percentage": "15%",
"value": "$250"
}
]
},
{
"artistId": "A002",
"artistName": "BW",
"songs": [{
"songId": "S001",
"songName": "Song 1",
"percentage": "10%",
"value": "$200"
},
{
"songId": "S002",
"songName": "Song 2",
"percentage": "10%",
"value": "$200"
}
]
},
{
"artistId": "A003",
"artistName": "POD",
"songs": [{
"songId": "S001",
"songName": "Song 1",
"percentage": "5%",
"value": "$150"
},
{
"songId": "S002",
"songName": "Song 2",
"percentage": "10%",
"value": "$200"
}
]
}
],
"summary": [{
"songName": "Song 1",
"totalPercentage": "25%",
"totalValue": "$550"
},
{
"songName": "Song 2",
"totalPercentage": "25%",
"totalValue": "$650"
}
]
}
I'm wondering could provided dataset be mapped in order to get something like on the sample table using angular material table? There is no need for pagination.
You should transform data by combining multiple rows into a single row by artist.
The transformed data should be looked as below:
[
{
"artistName": "Q1",
"percentage_0": "10%",
"value_0": "$200",
"percentage_1": "15%",
"value_1": "$250"
},
...,
{
"artistName": "SUM",
"percentage_0": "25%",
"value_0": "$550",
"percentage_1": "25%",
"value_1": "$650"
}
]
displayedColumns: string[] = ['artistName'];
firstHeaderColumns = ['_'];
transformDataSource: any[] = [];
ngOnInit() {
let songs = this.data.summary.map((x) => x.songName);
this.firstHeaderColumns = this.firstHeaderColumns.concat(songs);
this.displayedColumns = this.displayedColumns.concat(
...songs.map((x: string, i: number) => [`percentage_${i}`, `value_${i}`])
);
this.transformDataSource= this.data.data.map((x: any) => {
let obj: any = { artistName: x.artistName };
for (let i = 0; i < songs.length; i++) {
obj[`percentage_${i}`] = x.songs[i].percentage;
obj[`value_${i}`] = x.songs[i].value;
}
return obj;
});
let summary: any = { artistName: 'SUM' };
this.data.summary.forEach((x: any, i: number) => {
summary[`percentage_${i}`] = x.totalPercentage;
summary[`value_${i}`] = x.totalValue;
});
this.transformDataSource.push(summary);
}
<table mat-table [dataSource]="transformDataSource" class="mat-elevation-z8">
<ng-container *ngFor="let column of displayedColumns">
<ng-container matColumnDef="{{column}}">
<th mat-header-cell *matHeaderCellDef>
<ng-container
[ngTemplateOutlet]="headerTemplate"
[ngTemplateOutletContext]="{ $implicit: column }"
>
</ng-container>
</th>
<td mat-cell *matCellDef="let element">{{element[column]}}</td>
</ng-container>
</ng-container>
<ng-container *ngFor="let headerColumn of firstHeaderColumns">
<ng-container matColumnDef="{{headerColumn}}">
<th
mat-header-cell
*matHeaderCellDef
[attr.colspan]="headerColumn != '_' ? 2 : 1"
[style.text-align]="'center'"
>
{{headerColumn != '_' ? headerColumn : '' }}
</th>
</ng-container>
</ng-container>
<tr mat-header-row *matHeaderRowDef="firstHeaderColumns"></tr>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>
<ng-template let-prop #headerTemplate>
<ng-container [ngSwitch]="prop.split('_')[0]" [style.text-align]="'center'">
<ng-container *ngSwitchCase="'artistName'">Artist</ng-container>
<ng-container *ngSwitchCase="'percentage'">Perc %</ng-container>
<ng-container *ngSwitchCase="'value'">Value %</ng-container>
</ng-container>
</ng-template>