display the data of an array of one object in another object

Issue

enter image description hereI created an array with angular material, the array is created well but the problem that I can’t find a solution to display the array data of the object (I have an object contains arrays and this object is placed under another object).

how to display data of arrays that are in one object and that object is in another object.

i need to display the table as in the picture

model.ts:

export class visionCompacteDTOs {
        collaborator!:string;
        cetCP!:number;
        cetRTT!:number;
        perteRTT!:number;
        perteCP!:number;
        mnth:Month[]=[];
    }
    
    export class Month {
    month!: string;
    compteurFDP: Array<compteurFDP> =[];
    prisedemois: Array<prisesDuMois>=[];
    cmpteurfindumois: Array<compteurFinDuMois>=[];
}

export class compteurFDP {
    cp!:string;
    rtts!:number;
    rtte!:number;
}

export class prisesDuMois {
    cp!:number;
    rtts!:number;
    rtte!:number;
}

export class compteurFinDuMois {
    cp!:number;
    rtts!:number;
    rtte!:number;
    Somme!: number;
}

db.json:

{
    "visionCompacteDTO": [
        {
            "collaborator": "Jean",
            "cetCP": 0,
            "cetRTT": 0,
            "perteRTT": 3.56,
            "perteCP": 4,
            "mnth":  [
            {
                "month": "01/08/2021",
                "compteurFDP": {
                    "rtts":1.1,
                    "cp": 1.1,
                    "rtte": 1.1
                },
                "prisesDuMois": {
                    "rtts":1.1,
                    "cp": 1.1,
                    "rtte": 1.1
                },
                "compteurFinDuMois": {
                    "rtts":1.1,
                    "cp": 1.1,
                    "rtte": 1.1,
                    "somme": 1.1
                }
            },
            {
                "month": "01/09/2021",
                "compteurFDP": {
                    "rtts":0.0,
                    "cp": 0.0,
                    "rtte": 0.0
                },
                "prisesDuMois": {
                    "rtts":0.0,
                    "cp": 0.0,
                    "rtte": 0.0
                },
                "compteurFinDuMois": {
                    "rtts":0.0,
                    "cp": 0.0,
                    "rtte": 0.0,
                    "somme": 0.0
                }
            }                                             
        ]
        }
    ]
}

file.ts:

constructor(private reportingService: ReportingService) {}

  displayedColumns: string[] = [
    'collaborator',
    'cetCP',
    'cetRTT',
    //'moisSoldes',
    'perteRTTS',
    'perteRTTE',
    'perteCP'
    //'mnth'
  ];

  displayMonthColumns: string[] = [];
  displayFDPColumns: string[] = [];

  index: string[] = [
    'collaborator',
    'cetCP',
    'cetRTT',
    'perteRTTS',
    'moisSoldes',
    'perteRTTE',
    'perteCP',
    'mnth'
  ];

  dataSource: visionCompacteDTOs[] = [];
 
  ngOnInit(): void {
    this.reportingService.getNews().subscribe(
      (response: visionCompacteDTOs[]) => {
        if (!response) this.dataSource = response;
               
        for (let mnth of response[0].mnth) {
          this.displayedColumns.push(mnth.month);
          this.displayMonthColumns.push(mnth.month);
          this.displayFDPColumns.push(mnth.month);
        } 

        response = response.map(data => {
          let mnth = data.mnth;
          
          console.log(mnth[0].compteurFDP)

          let mnthObj: { [key: string]: number } = mnth.reduce((
            obj: { [key: string]: number },
            item
          ) => {

            console.log(mnth);
           // var fdp:any;
            for(var i=0; i< mnth.length; i++){
               this.fdp = mnth[i].compteurFDP
              for(let j=0; j < this.fdp.length; j++){
                obj[item.compteurFDP[j].cp] = item.compteurFDP[j].rtte = item.compteurFDP[j].rtts;
                return obj;
              }
              console.log(this.fdp);
            }
         //  obj[item.month] = item.compteurFDP[0].cp;
           console.log(this.fdp);
            return obj;
          },
          {});

          return {
            ...data,
            ...mnthObj
          };
        });

        this.dataSource = response;
       // console.log(response);
      },
      error => {
        console.log('Error Occured: ' + error);
      }
    );
  }

file.html :

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8 lftm">
  <ng-container matColumnDef="collaborateur">
    <th mat-header-cell *matHeaderCellDef> </th>
    <td mat-row *matCellDef="let element"> {{element.collaborateur}} </td>
  </ng-container>
      
  <ng-container *ngFor="let cp of displayMonthColumns">
    <ng-container matColumnDef="{{cp}}">
      <th mat-header-cell *matHeaderCellDef> {{cp}} </th>
      <td mat-cell *matCellDef="let element"> {{element[cp]}} </td>
    </ng-container>
  </ng-container>

  <ng-container matColumnDef="cetCP">
    <th mat-header-cell *matHeaderCellDef > CP </th>
    <td mat-cell *matCellDef="let element"> {{element.cetCP}} </td>
  </ng-container>
  <ng-container matColumnDef="cetRTT">
    <th mat-header-cell *matHeaderCellDef > RTT </th>
    <td mat-cell *matCellDef="let element"> {{element.cetRTT}} </td>
  </ng-container>
  <ng-container matColumnDef="perteRTTS">
    <th mat-header-cell *matHeaderCellDef > RTTS </th>
    <td mat-cell *matCellDef="let element"> {{element.perteRTTS}} </td>
  </ng-container>

  <ng-container matColumnDef="perteRTTE">
    <th mat-header-cell *matHeaderCellDef> RTTE </th>
    <td mat-cell *matCellDef="let element"> {{element.perteRTTE}} </td>
  </ng-container>
  <ng-container matColumnDef="perteCP">
    <th mat-header-cell *matHeaderCellDef> Perte CP </th>
    <td mat-cell *matCellDef="let element"> {{element.perteCP}} </td>
  </ng-container>

  <ng-container matColumnDef="header-row-do-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="1"> </th>
  </ng-container>
  <ng-container matColumnDef="header-row-first-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="2"> CET </th>
  </ng-container>
  <ng-container matColumnDef="header-row-nov-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="3"> </th>
  </ng-container>
  <ng-container matColumnDef="header-row-second-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="3"> Cpteur FDP </th>
  </ng-container>
  <ng-container matColumnDef="header-row-thirst-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="3">Prises du mois  </th>
  </ng-container>
  <ng-container matColumnDef="header-row-fourst-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="3"> Cpteur fin de mois </th>
  </ng-container>
  
  <ng-container matColumnDef="header-row-five-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="1">  </th>
  </ng-container>
  <ng-container matColumnDef="header-row-dec-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="1">  </th>
  </ng-container>
  <ng-container matColumnDef="header-row-jan-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="1">  </th>
  </ng-container>
  <ng-container matColumnDef="header-row-fevr-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="1">  </th>
  </ng-container>
  <ng-container matColumnDef="header-row-mars-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="1">  </th>
  </ng-container>
  
  <ng-container matColumnDef="header-row-avri-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="1">  </th>
  </ng-container>
  <ng-container matColumnDef="header-row-mai-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="1">  </th>
  </ng-container>
  <ng-container matColumnDef="header-row-juin-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="1"> </th>
  </ng-container>
  
  <ng-container matColumnDef="header-row-juil-group">
    <th mat-header-cell *matHeaderCellDef [attr.colspan]="1">  </th>
  </ng-container>
...
  ...
</table>

Solution

Concept

Column headers

1.1 displayFirstRowHeaders for first-row header columns, mainly hold monthYear. Example: ‘header-Aug-2021’.

1.1.1 These headers require rowspan=3 except monthYear.

1.1.2 monthYear headers require colspan=9.

1.2 displaySecondRowHeaders for second-row header columns. Example: ‘second-header-Aug-2021-compteurFDP’.

1.2.1 These headers require colspan=3.

1.3 displayedColumns for third-row header columns and data columns. Example: ‘Aug-2021-compteurFDP-cp’.

1.4 displayMonthColumns for generating columns via *ngFor.

Data Transformation

2.1 Generate object (mnthObj) from mnth with formatted month and item as key-value pair via reduce.

3.1 Create new array result with existing visionCompacteDTO object and mnthObj via map.


Solution

Pre-requisite:

  • Install moment via npm
npm install moment

.component.html

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8 lftm" *ngIf="dataSource && dataSource.length > 0">
  <ng-container matColumnDef="collaborator">
    <th mat-header-cell *matHeaderCellDef [ngStyle]="{'display': 'none'}"> No. </th>
    <td mat-cell *matCellDef="let element"> {{element.collaborator}} </td>
  </ng-container>

  <ng-container matColumnDef="header-row-first-group">
    <th mat-header-cell *matHeaderCellDef [attr.rowspan]="3"></th>
  </ng-container>

  <ng-container matColumnDef="cetCP">
    <th mat-header-cell *matHeaderCellDef [ngStyle]="{'display': 'none'}"> CP </th>
    <td mat-cell *matCellDef="let element"> {{element.cetCP}} </td>
  </ng-container>

  <ng-container matColumnDef="header-row-second-group">
    <th mat-header-cell *matHeaderCellDef [attr.rowspan]="3"> CP </th>
  </ng-container>

  <ng-container matColumnDef="cetRTT">
    <th mat-header-cell *matHeaderCellDef [ngStyle]="{'display': 'none'}"> RTT </th>
    <td mat-cell *matCellDef="let element" [attr.rowspan]="3"> {{element.cetRTT}} </td>
  </ng-container>

  <ng-container matColumnDef="header-row-third-group">
    <th mat-header-cell *matHeaderCellDef [attr.rowspan]="3"> RTT </th>
  </ng-container>

  <ng-container *ngFor="let month of displayMonthColumns">

    <!-- Month Year Header Column-->
    <ng-container matColumnDef="{{ 'header-' + month}}">
      <th mat-header-cell *matHeaderCellDef [attr.colspan]="9"> {{month}}</th>
    </ng-container>

    <!-- compteurFDP Second Header Column-->
    <ng-container matColumnDef="{{ 'second-header-' + month + '-compteurFDP' }}">
      <th mat-header-cell *matHeaderCellDef [attr.colspan]="3"> compteurFDP </th>
    </ng-container>

    <!-- compteurFDP Third Header Column-->
    <ng-container matColumnDef="{{month + '-compteurFDP-cp' }}">
      <th mat-header-cell *matHeaderCellDef> CP </th>
      <td mat-cell *matCellDef="let element"> {{element[month].compteurFDP.cp}} </td>
    </ng-container>

    <ng-container matColumnDef="{{month + '-compteurFDP-rtts'}}">
      <th mat-header-cell *matHeaderCellDef> RTTS </th>
      <td mat-cell *matCellDef="let element"> {{element[month].compteurFDP.rtts}} </td>
    </ng-container>

    <ng-container matColumnDef="{{month + '-compteurFDP-rtte'}}">
      <th mat-header-cell *matHeaderCellDef> RTTE </th>
      <td mat-cell *matCellDef="let element"> {{element[month].compteurFDP.rtte}} </td>
    </ng-container>

    <!-- compteurFinDuMois Second Header Column-->
    <ng-container matColumnDef="{{ 'second-header-' + month + '-compteurFinDuMois' }}">
      <th mat-header-cell *matHeaderCellDef [attr.colspan]="3"> compteurFinDuMois </th>
    </ng-container>

    <!-- compteurFinDuMois Third Header Column-->
    <ng-container matColumnDef="{{month + '-compteurFinDuMois-cp' }}">
      <th mat-header-cell *matHeaderCellDef> CP </th>
      <td mat-cell *matCellDef="let element"> {{element[month].compteurFinDuMois.cp}} </td>
    </ng-container>

    <ng-container matColumnDef="{{month + '-compteurFinDuMois-rtts'}}">
      <th mat-header-cell *matHeaderCellDef> RTTS </th>
      <td mat-cell *matCellDef="let element"> {{element[month].compteurFinDuMois.rtts}} </td>
    </ng-container>

    <ng-container matColumnDef="{{month + '-compteurFinDuMois-rtte'}}">
      <th mat-header-cell *matHeaderCellDef> RTTE </th>
      <td mat-cell *matCellDef="let element"> {{element[month].compteurFinDuMois.rtte}} </td>
    </ng-container>

    <!-- prisesDuMois Second Header Column-->
    <ng-container matColumnDef="{{ 'second-header-' + month + '-prisesDuMois' }}">
      <th mat-header-cell *matHeaderCellDef [attr.colspan]="3"> prisesDuMois </th>
    </ng-container>

    <!-- prisesDuMois Third Header Column-->
    <ng-container matColumnDef="{{month + '-prisesDuMois-cp' }}">
      <th mat-header-cell *matHeaderCellDef> CP </th>
      <td mat-cell *matCellDef="let element"> {{element[month].prisesDuMois.cp}} </td>
    </ng-container>

    <ng-container matColumnDef="{{month + '-prisesDuMois-rtts'}}">
      <th mat-header-cell *matHeaderCellDef> RTTS </th>
      <td mat-cell *matCellDef="let element"> {{element[month].prisesDuMois.rtts}} </td>
    </ng-container>

    <ng-container matColumnDef="{{month + '-prisesDuMois-rtte'}}">
      <th mat-header-cell *matHeaderCellDef> RTTE </th>
      <td mat-cell *matCellDef="let element"> {{element[month].prisesDuMois.rtte}} </td>
    </ng-container>

  </ng-container>

  <tr mat-header-row *matHeaderRowDef="displayFirstRowHeaders"></tr>
  <tr mat-header-row *matHeaderRowDef="displaySecondRowHeaders"></tr>
  <tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
  <tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>

</table>

.component.ts

import moment = require('moment');

export class CompacteComponent implements OnInit {
  ...

  displayedColumns: string[] = ['collaborator', 'cetCP', 'cetRTT'];

  displayMonthColumns: string[] = [];

  displayFirstRowHeaders: string[] = [
    'header-row-first-group',
    'header-row-second-group',
    'header-row-third-group'
  ];
  displaySecondRowHeaders: string[] = [];

  nestedColumns: { [key: string]: string[] } = {
    compteurFDP: ['cp', 'rtts', 'rtte'],
    compteurFinDuMois: ['cp', 'rtts', 'rtte'],
    prisesDuMois: ['cp', 'rtts', 'rtte']
  };

  dataSource: visionCompacteDTOs[] = [];

  ngOnInit(): void {
    this.reportingService.getNews().subscribe(
      (response: visionCompacteDTOs[]) => {
        if (!response) this.dataSource = response;

        if (response.length == 0) this.dataSource = response;

        for (let mnth of response[0].mnth) {
          let date = moment(mnth.month, 'DD/MM/YYYY');
          let monthYear = date.format('MMM-YYYY');

          // Generate display month
          this.displayMonthColumns.push(monthYear);

          // Generate First Row Header
          this.displayFirstRowHeaders.push(`header-${monthYear}`);

          for (let col in this.nestedColumns) {
            // Generate First Row Header
            this.displaySecondRowHeaders.push(
              `second-header-${monthYear}-${col}`
            );

            // Generate displayed columns or Third Row Header
            for (let innerCol of this.nestedColumns[col])
              this.displayedColumns.push(`${monthYear}-${col}-${innerCol}`);
          }
        }

        response = response.map(data => {
          let mnth = data.mnth;

          let mnthObj: { [key: string]: any } = mnth.reduce(
            (obj: { [key: string]: any }, item) => {
              let date = moment(item.month, 'DD/MM/YYYY');
              let monthYear = date.format('MMM-YYYY');
              obj[monthYear] = item;

              return obj;
            },
            {}
          );

          return {
            ...data,
            ...mnthObj
          };
        });

        this.dataSource = response;
        console.log('Response', response);
      },
      error => {
        console.log('Error Occured: ' + error);
      }
    );
  }
}

.component.css

th.mat-header-cell,
td.mat-cell {
  text-align: center;
  border: 1px solid #ccc;
  padding: 0 !important;
}

Sample Solution on StackBlitz

Result

Answered By – Yong Shun

Answer Checked By – Senaida (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.