score:3

Accepted answer

look the problem is that your numberByStatus object reference doesn't change when you are trying to push the items into labelsByStatus or countsByStatus arrays

try like this.

**at first import all of these items for both solutions

import { forkJoin } from 'rxjs/internal/observable/forkJoin';
import { map } from 'rxjs/operators';

and

numberByStatus : any;
labelsByStatus: String[] = [];
countsByStatus: number[] = [];


this.service.getStatus()
  .subscribe((res: status[]) => {

    const requestsList = [];   // define the request list property and store all of the requests here
    res.forEach(element => {  
    // push the request into the array
    requestsList.push(
       this.service.getCountByStatus(element.id).pipe(
          map(count => {   
              // push the count into countsByStatus
              this.countsByStatus.push(count);
              // push the element.designation into labelsByStatus
              this.labelsByStatus.push(element.designation);
              // return the count and the corresponding element
              // I think this can be helpfull. if you will need to know the count for the each element
              return { element: element, count: count }
          }))
       );

    });  
       // send all of the requests
       forkJoin(requestsList).subscribe(
             (response: {element: status, count: number}[]) => {
               // and now this line will work only once
                this.numberByStatus = { ...this.numberByStatus };
             },
             (err) => {
                alert('Faild to load data');
             }
        );

  }, (err) => {
    alert('Faild to load data');
  });

 this.numberByStatus = {
    labels: this.labelsByStatus,
    datasets: [
       {
           data: this.countsByStatus,
           backgroundColor: [
              "#FF6384",
              "#36A2EB",
              "#FFCE56"
           ],
           hoverBackgroundColor: [
              "#FF6384",
              "#36A2EB",
              "#FFCE56"
           ]
       }
    ]

 };

or

numberByStatus : any;
labelsByStatus: String[] = [];
countsByStatus: number[] = [];


this.service.getStatus()
  .subscribe((res: status[]) => {

    const requestsList = [];   // define the request list property and store all of the requests here
    res.forEach(element => {  
    // push the request into the array
    requestsList.push(
       this.service.getCountByStatus(element.id).pipe(
          map(count => {   
               // push the count into countsByStatus
              this.countsByStatus.push(count);
              // push the element.designation into labelsByStatus
              this.labelsByStatus.push(element.designation);
              // return the count and the corresponding element
              // I think this can be helpfull. if you will need to know the count for the each element
              return { element: element, count: count }
          }))
       );
    });  
    
       forkJoin(requestsList).subscribe(
             (response: {element: status, count: number}[]) => {
              // and now this line will work only once
               this.numberByStatus = {
                   labels: this.labelsByStatus,
                   datasets: [
                      {
                         data: this.countsByStatus,
                         backgroundColor: [
                             "#FF6384",
                             "#36A2EB",
                             "#FFCE56"
                         ],
                         hoverBackgroundColor: [
                             "#FF6384",
                             "#36A2EB",
                             "#FFCE56"
                         ]
                     }
                 ]

             };
    
             },
             (err) => {
                alert('Faild to load data');
             }
          );

  }, (err) => {
    alert('Faild to load data');
  });

score:0

The problem is due to the asynchronous nature of Angular. The chart is created before its labels and the data have been defined inside this.numberByStatus.

There are basically two solutions to solve this issue.

  1. Make sure the chart is created only once this.numberByStatus is fully furnished.
  2. Update the chart programmatically after this.numberByStatus is completely defined.

Without seeing more of your code, its hard to provide the best solution however. I also don't know primeng-lts.

  • You could try to only conditionally include the chart in your HTML template using *ngIf. It should evaluate to true only once this.numberByStatus is ready to be used (solution 1).
  • In case you can obtain a reference to the chart object, invoke its update() method after you redefined this.numberByStatus (solution 2).

Related Query

More Query from same tag