Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

This is really my first time using Chart.js and I am importing it into an Angular component. I am trying to at this point just create a simple bar chart. I am getting the following error in my console:

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

not sure what I am doing wrong here!

this is the TS file for my component:

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

}

and then my template is simply:

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

I also wanted to go on record saying that i tried this fix chart.js Failed to create chart: can't acquire context from the given item and still go the same error!

like image 546
Sandra Willford Avatar asked Jan 01 '18 00:01

Sandra Willford


2 Answers

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

    }

}
like image 55
pixelbits Avatar answered Oct 22 '22 00:10

pixelbits


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.

like image 20
michaeak Avatar answered Oct 22 '22 00:10

michaeak