1

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.

1 Answer 1

0

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>

Demo @ StackBlitz

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.