Angular/Chart.js error: Failed to create chart: can't acquire context from the given item

Solution 1:

If you look at the documentation for creating a chart in Chart.js, the first parameter is a context obtained from a DOM element, and not a string:

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

You can get a reference to the DOM element by using template variables and ElementRef:

HTML

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

Tyepscript:

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

    }

}

Solution 2:

I use Angular 6 and the answer that was there was not too helpful, even if it advanced me in solving the issue. There are several pitfalls to circumvent.

First the html of the part, important is the #chart so it can be referenced in the component.ts file. The other important is the class chart of the div with which the size can be managed via css:

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

}

Additionally in the package.json there where added things, for reference: For dependencies the line "chart.js": "^2.7.3", and for devDependencies the line "@types/chart.js": "^2.7.42", was added.

In this way the graph should be displayed properly.

Solution 3:

I had the same problem and Finally I found the solution.

Insert this in the html file:

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

While your ts file has the following shape:

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

As you can see the solution is to initialize chartRef:

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

After migration to Angular 8 you should declare manually if it's static or not, if you don't add {static: true}, by compiling you will have error for missing argument. Than you can easily create your chart in this way:

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

Solution 4:

I know this is an old thread, but I could not get any of these solutions to work for angular 9. After some research I've found a much simpler solution

For the html

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

For the Component.ts file

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