在另一个对象中显示一个对象数组的数据

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

enter image description here我用angular material创建了一个数组,这个数组创建的很好但是我找不到显示对象数组数据的解决方案的问题(我有一个对象包含数组,此对象位于另一个对象下)。

如何显示一个对象中的数组数据以及该对象在另一个对象中的数据。

我需要显示table如图

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>

概念

列headers

1.1 displayFirstRowHeaders for first-row header 列,主要持有monthYear。示例:'header-Aug-2021'.

1.1.1 除了 monthYear.

这些 header 需要 rowspan=3

1.1.2 monthYear header需要colspan=9.

1.2 displaySecondRowHeaders 用于 second-row header 列。示例:'second-header-Aug-2021-compteurFDP'.

1.2.1 这些 header 需要 colspan=3.

1.3 displayedColumns for third-row header 列和数据列。示例:'Aug-2021-compteurFDP-cp'.

1.4 displayMonthColumns 用于通过 *ngFor.

生成列

数据转换

2.1mnth 生成 object (mnthObj),格式为 monthitem key-value 对通过 reduce.

3.1 通过映射使用现有 visionCompacteDTO object 和 mnthObj 创建新数组结果。


解决方案

Pre-requisite:

  • 通过 npm 安装 moment
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