-1

the table works almost well, the problem is that all the "solde" values ​​appear in the same column.

I want to display each balance and month value in a column, I tried to loop "mnth" but it doesn't work

this table is dynamically how to display each solde value in a different column ?

export class visionCompacteDTOs {
    collaborator!:string;
    cetCP!:number;
    cetRTT!:number;
    perteRTT!:number;
    perteCP!:number;
    mnth:Month[]=[];
}

export class Month {
  month!: Date;
  solde!: number;
}

db.json :

{
    "visionCompacteDTO": [
        {
            "collaborator": "Jean",
            "cetCP": 0,
            "cetRTT": 0,
            "perteRTT": 3.56,
            "perteCP": 4,
            "mnth": [
                {
                 "month": "July",
                 "solde": 14.52
                },
                {
                 "month": "August",
                 "solde": 15.52
                },
                {
                 "month": "September",
                 "solde": 16.52
                },
                {
                    "month": "October",
                    "solde": 18.52
                },
                {
                    "month": "November",
                    "solde": 19.52
                },
                {
                    "month": "December",
                    "solde": 20.52
                }
            ]
        }
    ]
}

file.ts:

export class CompacteComponent {
  don: any;
  sld:any;
  userdata:any=[];
  constructor(private reportingService:ReportingService) { }

  columns: string[] = ['collaborator', 'cetCP', 'cetRTT', 'moisSoldes', 'perteRTT', 'perteCP','mnth'];
  index: string[] = ['collaborator', 'cetCP', 'cetRTT', 'moisSoldes', 'perteRTT', 'perteCP','mnth'];

  dataSource :visionCompacteDTOs[] = [];
  
  ngOnInit():void {
    
    this.reportingService.getNews().subscribe((response)=>{
      this.dataSource = response;
      console.log(response)
      for (let i = 0; i < response.length; i++) {
        var username:any = this.dataSource[i].mnth;
        this.userdata = username;
        console.log(this.userdata);
        for (let j = 0; j < username.length; j++) {
          this.don = username[j].month;
          this.sld = this.userdata[j].solde;
          console.log(this.sld);
        }
      }
    },
    (error)=>{
      console.log("Error Occured: "+error);
    }
    )
  }

}

file.html :

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8 lftm">
  <ng-container matColumnDef="collaborator">
    <th mat-header-cell *matHeaderCellDef> </th>
    <td mat-row *matCellDef="let element"> {{element.collaborator}} </td>
  </ng-container>
  
  <ng-container matColumnDef="cetCP">
    <th mat-header-cell *matHeaderCellDef > cetCP </th>
    <td mat-cell *matCellDef="let element"> {{element.cetCP}} </td>
  </ng-container>
  <ng-container matColumnDef="cetRTT">
    <th mat-header-cell *matHeaderCellDef > cetRTT </th>
    <td mat-cell *matCellDef="let element"> {{element.cetRTT}} </td>
  </ng-container>

   
  <ng-container  matColumnDef="mnth">
    <th mat-header-cell *matHeaderCellDef >
      <span *ngFor="let solde of this.userdata"> {{solde.month}} </span></th>
    <td mat-cell *matCellDef="let element" >
      <span *ngFor="let loc of this.userdata"> {{loc.solde}}</span>  </td>
  </ng-container>

  <ng-container matColumnDef="perteRTT">
    <th mat-header-cell *matHeaderCellDef class="prt"> Perte RTT </th>
    <td mat-cell *matCellDef="let element"> {{element.perteRTT}} </td>
  </ng-container>
  <ng-container matColumnDef="perteCP">
    <th mat-header-cell *matHeaderCellDef class="prt"> Perte CP </th>
    <td mat-cell *matCellDef="let element"> {{element.perteCP}} </td>
  </ng-container>
...
...
Yong Shun
  • 35,286
  • 4
  • 24
  • 46
adam
  • 33
  • 5

1 Answers1

1

Concept (in short)

1.0 Retrieve first row's mnth and add into displayedColumns and displayedMonthColumns arrays.

1.1 Add into displayedColumns for the columns must be existed and be required by mat-header-row and mat-row.

1.2 Add into displayedMonthColumns for generating columns via *ngFor.

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

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


Solution

.component.html

<table mat-table [dataSource]="dataSource" class="mat-elevation-z8 lftm">
  ...

  <ng-container *ngFor="let month of displayMonthColumns">
    <ng-container matColumnDef="{{month}}">
      <th mat-header-cell *matHeaderCellDef> {{month}} </th>
      <td mat-cell *matCellDef="let element"> {{element[month]}} </td>
    </ng-container>
  </ng-container>
</table>

.component.ts

export class CompacteComponent implements OnInit {

  ...

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

  displayMonthColumns: string[] = [];

  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);
        }

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

          let mnthObj: { [key: string]: number } = mnth.reduce(function(
            obj: { [key: string]: number },
            item
          ) {
            obj[item.month] = item.solde;
            return obj;
          },
          {});

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

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

Sample Solution on StackBlitz

Result

Yong Shun
  • 35,286
  • 4
  • 24
  • 46
  • thank's for your answer, but it show me this error : Element implicitly has an 'any' type because expression of type 'string' can't be used to index type '{}'. No index signature with a parameter of type 'string' was found on type '{}'. 55 obj[item.month] = item.solde; – adam Sep 06 '21 at 12:07
  • Hi updated my answer for the `noImpicitAny` fix. You may refer to this [question](https://stackoverflow.com/q/32968332/8017690). – Yong Shun Sep 06 '21 at 13:01
  • thank's for first example it's work, but now i changed the db.json database(i added array in object month) and the model (visionCompacteDTOs ), do i have to do the same to display the table ? and thank's – adam Sep 08 '21 at 08:46
  • Hi, I saw the response data structure changed quite a lot. I doubt the changes in the response data will break the current solution. Anyway, would suggest you to create another question **but not updating the current question** as the answer is designed based on the original question. Looking forward to your new question. – Yong Shun Sep 08 '21 at 08:55
  • I want to replace the column perteRTT after the column September and the column perteCP after the column November, I can do this with *ngFor ? – adam Sep 09 '21 at 19:08
  • Hi, you cannot re-positioning perteRTT and perteCP with `*ngFor` as the array used for holding and generating the month by sequence. Maybe you need to think to restructure your data and table. – Yong Shun Sep 10 '21 at 10:08
  • unfortunately I did not find a solution – adam Sep 13 '21 at 14:03