Chart.js 在放大 angular 8 之前不会呈现

Chart.js is not rendered until zoom in in angular 8

我有一个 angular 8 应用程序,我正在使用 primeng-lts 8.2.5 组件,我正在尝试在我的应用程序中使用 chart.js 版本 2.9.3,但是在我放大之前,饼图和标签都不会显示。

在我的饼图中,我按状态显示计数,如下面的代码所示,我从 http 调用加载 status[],然后对于每个 status,我调用return 计数的 http 方法:

HTML :

<p-chart type="pie" [data]="numberByStatus" >
</p-chart>

TS :

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


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


    res.forEach(element => {         
    this.service.getCountByStatus(element.id)
        .subscribe((count: number) => {
          this.countsByStatus.push(count);
          this.labelsByStatus.push(element.designation)
        }, (err) => {
          alert('Faild to load counts');
        });
    });


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


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

问题是由于 Angular 的异步性质造成的。该图表是在其 labels 之前创建的,并且 data 已在 this.numberByStatus.

中定义

基本上有两种方法可以解决这个问题。

  1. 确保仅在 this.numberByStatus 家具齐全后才创建图表。
  2. this.numberByStatus 完全定义后以编程方式更新图表。

在没有看到更多代码的情况下,很难提供最佳解决方案。我也不知道primeng-lts.

  • 您可以尝试使用 *ngIf 有条件地将图表包含在您的 HTML 模板中。只有在 this.numberByStatus 准备好使用(解决方案 1)后,它才应评估为 true
  • 如果您可以获得对 chart 对象的引用,请在重新定义 this.numberByStatus 后调用其 update() 方法(解决方案 2)。

问题在于,当您尝试将项目推入 labelsByStatuscountsByStatus 数组时,您的 numberByStatus 对象引用没有改变

这样试试。

**首先为两种解决方案导入所有这些项目

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

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"
           ]
       }
    ]

 };

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