0

我可以在一个非常简单的 Angular-Hicharts 应用程序中重现该问题。当我从服务器检索数据,然后离开带有 Highcharts 图表的页面时,我收到此错误:

无法在 HighchartsChartComponent.ngOnDestroy (highcharts-angular.js:44) 的 a.destroy (highcharts.js:394) 处读取未定义的属性“forExport”

不足为奇的HighchartsChartComponent.ngOnDestroy

ngOnDestroy() {
    if (this.chart) { // #56
        this.chart.destroy();
        this.chart = null;
    }
}

这是最小的示例:

export class WeatherForecastComponent implements OnInit {
  highcharts: typeof Highcharts = Highcharts;
  chartOptions: Highcharts.Options = { ... };

constructor(private http: HttpClient) { }

ngOnInit(): void {
    this.http.get<any[]>(`http://localhost:57432/WeatherForecast`, {
        headers: new HttpHeaders({
            "Content-Type": "application/json"
    })})
    .subscribe(result => {
        let categories: string[] = [];
        let dataSeries: number[] = [];
        for (let i = 0; i < result.length; i++) {
            categories.push(result[i]['location']);
            dataSeries.push(result[i]['temperatureC']);
        }
        this.chartOptions.xAxis = {
            categories: categories
        };
        this.chartOptions.series = [{
          type: "column",
          name: "Cities",
          data: dataSeries
        }];
     this.highcharts.chart('container', this.chartOptions);
     }, error => {
         console.log(error);
     });
  }
}

我在 Stack Overflow 和 Github 上都看到了许多类似的问题。我知道根本原因是它正在尝试删除已删除的图表。但他们都在删除(或试图删除)应用程序代码中的图表。

我试图删除 中的图表ngOnDestroy(),或取消订阅 - 但没有区别。

这是repo,包括服务器端代码。

请注意,当它是“硬编码”图表时,问题不会发生。

角度:12.2;Highchars 9.2.2;Highcharts-Angular:2.10.0

4

2 回答 2

0

在您的代码中,有一件事是不必要的,它会导致该问题。
您不必在此处销毁图表参考。当您删除时,一切都按预期工作。

ngOnDestroy() {
   this.chartRef.destroy()
}

另请注意,在内部创建第二个图表subscribe并不理想。安装使用updateFlag

this.highcharts.chart('container', this.chartOptions);

演示:https ://stackblitz.com/edit/highcharts-angular-basic-line-nxzqvy

于 2021-09-09T09:59:23.470 回答
0

有两个主要的东西不起作用。但在我解释之前,让我们看看负责在包装器中创建图表的代码。

ngOnChanges(changes) {
        const update = changes.update && changes.update.currentValue;
        if (changes.options || update) {
            this.wrappedUpdateOrCreateChart();
            if (update) {
                this.updateChange.emit(false); // clear the flag after update
            }
        }
    }
    wrappedUpdateOrCreateChart() {
        if (this.runOutsideAngular) {
            this._zone.runOutsideAngular(() => {
                this.updateOrCreateChart();
            });
        }
        else {
            this.updateOrCreateChart();
        }
    }
    updateOrCreateChart() {
        if (this.chart && this.chart.update) {
            this.chart.update(this.options, true, this.oneToOne || false);
        }
        else {
            this.chart = this.Highcharts[this.constructorType || 'chart'](this.el.nativeElement, this.options, this.callbackFunction || null);
            // emit chart instance on init
            this.chartInstance.emit(this.chart);
        }
    }

正如你所看到的,一切都发生在ngOnChanges钩子里。如果检测到更改,则会触发一系列方法以最终更新图表。

现在不起作用的事情:

  1. 如果发生任何异步代码subscribe(例如 HTTP 请求 - 在我的示例中由 模拟setTimeout),您必须手动设置为应该通过设置updateFlag. 因为 Angular 不会检测chartOptions.

  2. chartOptions如果您在下面的代码片段中将分配属性拆分为类似,请将oneToOne标志设置为true

     this.chartOptions.xAxis = {
            categories: categories
          };
          this.chartOptions.series = [{
            type: "column",
            name: "Cities",
            data: dataSeries
          }];

文档:https
://github.com/highcharts/highcharts-angular#options-details 演示:https ://stackblitz.com/edit/highcharts-angular-basic-line-vwrrmx

于 2021-09-13T13:46:58.837 回答