【问题标题】:Angular/Chart.js error: Failed to create chart: can't acquire context from the given itemAngular/Chart.js 错误:无法创建图表:无法从给定项目获取上下文
【发布时间】:2018-01-01 00:02:28
【问题描述】:

这真的是我第一次使用 Chart.js,我将它导入到一个 Angular 组件中。我试图在这一点上创建一个简单的条形图。我在控制台中收到以下错误:

core.controller.js:118 Failed to create chart: can't acquire context from the given item

不知道我在这里做错了什么!

这是我的组件的 TS 文件:

import { Component, OnInit } from '@angular/core';
import { Chart } from 'chart.js';
import { data } from './data';

@Component({
  selector: 'app-propel-factor',
  templateUrl: './propel-factor.component.html'
})
export class PropelFactorComponent implements OnInit {

    chart = [];
    labels: any = [];

    data: any = [];

    constructor() { }

    ngOnInit() {
        data.forEach(item => {
            this.labels.push(item.name);
            this.data.push(item.value);
        });

        this.chart = new Chart('canvas', {
            type: 'bar',
            labels: this.labels,
            data: {
                labels: this.labels,
                data: this.data
            },
            options: {
                responsive: true
            }
        });
    }

}

然后我的模板就是:

<div *ngIf="chart">
    <canvas id="canvas">{{ chart }}</canvas>
</div>

我还想公开表示我尝试了此修复 chart.js Failed to create chart: can't acquire context from the given item 并且仍然出现相同的错误!

【问题讨论】:

  • 这个答案可能会帮助您开始使用 chart.js:stackoverflow.com/questions/46328575/…
  • @Z.Bagley 非常感谢。
  • 你能解决这个问题吗...?如果您已解决此问题,请添加您的答案。

标签: javascript angular


【解决方案1】:

如果您查看Chart.js 中创建图表的文档,第一个参数是从 DOM 元素获取的上下文,而不是字符串:

var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {

您可以通过使用模板变量和 ElementRef 来获取对 DOM 元素的引用:

HTML

<div *ngIf="chart">
    <canvas #canvas id="canvas">{{ chart }}</canvas>
</div>

打字稿:

import { Component, OnInit, AfterViewInit, ElementRef, ViewChild } from '@angular/core';
import { Chart } from 'chart.js';
import { data } from './data';

@Component({
  selector: 'app-propel-factor',
  templateUrl: './propel-factor.component.html'
})
export class PropelFactorComponent implements OnInit, AfterViewInit {
    @ViewChild('canvas') canvas: ElementRef;

    chart = [];
    labels: any = [];

    data: any = [];

    constructor() { }

    ngOnInit() {
        data.forEach(item => {
            this.labels.push(item.name);
            this.data.push(item.value);
        });

    }
    ngAfterViewInit() {
        this.chart = new Chart(this.canvas.nativeElement.getContext('2d'), {
            type: 'bar',
            labels: this.labels,
            data: {
                labels: this.labels,
                data: this.data
            },
            options: {
                responsive: true
            }
        });

    }

}

【讨论】:

  • TS 投诉ERROR in src/app/components/dashboard/propel-factor/propel-factor.component.ts(24,55): error TS2339: Property 'getContext' does not exist on type 'HTMLElement'.
  • 查看有关如何使用 chart.js 的文档:chartjs.org/docs/latest/getting-started。看起来您可能缺少脚本?
  • 好像还少了一个AfterViewInit
  • 我认为存在先天不足的问题,至少当我尝试使用您建议的答案时。如果你有 *ngIf="chart" 图表是未定义的并且不能使用,因为它只会在onAfterViewInit 之后定义,这为时已晚。那么html中的{{ chart }}部分会导致异常,这个[object object]的输出根本就没用了。
  • 在文档中,字符串的第一个参数也是可以接受的。见:chartjs.org/docs/latest/getting-started/…
【解决方案2】:

我使用 Angular 6 并且那里的答案并没有太大帮助,即使它帮助我解决了问题。有几个陷阱需要规避。

首先是部件的html,重要的是#chart,所以它可以在component.ts文件中被引用。另一个重要的是可以通过css管理大小的div的类图:

<div class="chart">
  <canvas #chart ></canvas>
</div>

css:

div.chart {
  width: 600px;
  height: 300px;
}

component.ts:

import {Component, ElementRef, OnInit, ViewChild} from '@angular/core';

import {Chart} from 'chart.js';

@Component({
  selector: 'app-report-quarterly',
  templateUrl: './report-quarterly.component.html',
  styleUrls: ['./report-quarterly.component.css']
})
export class ReportQuarterlyComponent implements OnInit {

  @ViewChild('chart') chartElementRef: ElementRef;

  chart : Chart;

  constructor() { }

  ngOnInit() {
    let context = this.chartElementRef.nativeElement;
    let data = { ... };  // data to be filled with meaningful data.
    this.chart = new Chart(context, data );
  }

}

另外在package.json那里添加了东西,供参考: 对于dependencies,添加了"chart.js": "^2.7.3", 行,对于devDependencies,添加了"@types/chart.js": "^2.7.42", 行。

这样图表应该可以正常显示了。

【讨论】:

  • 只是补充一点,我建议使用AfterViewInit 钩子,而不是OnInit
  • 感谢您的评论。当数据发生变化时,这会使图表刷新吗?
【解决方案3】:

我遇到了同样的问题,最后我找到了解决方案。

在 html 文件中插入:

<div style="display: block">
<canvas #lineChart>{{ chart }}</canvas>
</div>

虽然您的 ts 文件具有以下形状:

import { Component, OnInit, ViewChild } from '@angular/core';
import { Chart } from 'chart.js';
...
export class MyComponent implements OnInit {
  @ViewChild('lineChart', {static: true}) private chartRef;
  chart : any;
  month = [];
  price = [];

  constructor() { }

  ngOnInit() {

    this.month = ['January', 'February', 'March', 'April', 'May', 'June', 'July'];
    this.price = [10,20,30,40,50,40,10];
    this.chart = new Chart(this.chartRef.nativeElement,{
    type: 'line',
        data: {
          labels: this.month,
          datasets: [
            {
              data: this.price,
              borderColor: '#3cba9f',
              fill: false
            }
          ]
        },
        options: {
          legend: {
            display: false
          },
          scales: {
            xAxes: [{
              display: true
            }],
            yAxes: [{
              display: true
            }],
          }
        }
        });
  }
}

如您所见,解决方案是初始化chartRef:

@ViewChild('lineChart', {static: true}) private chartRef;

在迁移到 Angular 8 后,你应该手动声明它是否是静态的,如果你不添加 {static: true},通过编译你会因为缺少参数而出错。您可以通过这种方式轻松创建图表:

this.chart = new Chart(this.chartRef.nativeElement,{ ... });

【讨论】:

    【解决方案4】:

    我知道这是一个旧线程,但我无法让这些解决方案中的任何一个适用于 angular 9。经过一些研究,我发现了一个更简单的解决方案

    对于html

       <div>
         <canvas id="myChart"></canvas>
       </div>
    

    对于 Component.ts 文件

    import { Component } from '@angular/core';
    import { Chart } from 'chart.js';
    
    ...
    
    export class AppComponent {
      constructor() {}
    
      canvas: any;
      ctx: any;
    
      ngAfterViewInit() {
        this.canvas = document.getElementById('myChart');
        this.ctx = this.canvas.getContext('2d');
    
        let chart = new Chart( this.ctx, {data});
      }
    }
    
    

    【讨论】:

    • 不应直接以角度访问 DOM 代码。请检查@Pittuzzo 代码。
    【解决方案5】:

    只需简单地将 Chart() 中的 chartItemid 属性匹配即可。

    示例:

    this.chart = new Chart("myChart", ...);
    ...
    <canvas id="myChart">{{chart}}</canvas>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-07
      • 1970-01-01
      • 1970-01-01
      • 2020-07-10
      • 2019-10-21
      • 2020-09-18
      • 2021-06-14
      • 1970-01-01
      相关资源
      最近更新 更多