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!
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
}
});
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With