I am trying to implement a plot into a ionic component based on these examples: https://enappd.com/blog/charts-in-ionic-4-apps-and-pwa-part-1/52/
I simply copy & paste the stuff into a component but when I run the component the @ViewChild
will not be found. I tried it with the ionic native @ViewChild
option and with document.getElementByID
but both will not return the plot element.
this.barChart
. will be undefined and crash the createBarChart
function.
I have the feeling that because it is a component the document.getElementByID
searches the parent document tree and not the component document.
HTML:
<ion-content>
<ion-card class="welcome-card">
<ion-card-header>
<ion-card-subtitle>Number of Viewers per season for</ion-card-subtitle>
<ion-card-title>Game of Thrones</ion-card-title>
</ion-card-header>
<ion-card-content>
<canvas #barChart></canvas>
</ion-card-content>
</ion-card>
</ion-content>
TS
import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Chart } from 'chart.js';
@Component({
selector: 'app-plot',
templateUrl: './plot.component.html',
styleUrls: ['./plot.component.scss'],
})
export class PlotComponent implements OnInit {
@ViewChild('barChart') barChart: ElementRef;
bars: any;
colorArray: any;
constructor() { }
ngOnInit() {
this.createBarChart();
}
createBarChart() {
this.bars = new Chart(this.barChart.nativeElement, {
type: 'bar',
data: {
labels: ['S1', 'S2', 'S3', 'S4', 'S5', 'S6', 'S7', 'S8'],
datasets: [{
label: 'Viewers in millions',
data: [2.5, 3.8, 5, 6.9, 6.9, 7.5, 10, 17],
backgroundColor: 'rgb(38, 194, 129)', // array should have same number of elements as number of dataset
borderColor: 'rgb(38, 194, 129)', // array should have same number of elements as number of dataset
borderWidth: 1
}]
},
options: {
scales: {
yAxes: [{
ticks: {
beginAtZero: true
}
}]
}
}
});
}
}
As @fridoo mentioned you are trying to initialize a dom element inside ngOnInit hook, whereas the template code has not been initialized yet.
Specifically with HTMLCanvasElement it is best to use Ionic's IonViewDidEnter hook as then your Canvas element and other elements (such as ion-header) will fully initialize and you will be able to reliably refer to the element as well is its offsets.
You can see it this way:
import { Component, ViewChild, ElementRef } from '@angular/core';
import { AlertController } from '@ionic/angular';
@Component({
selector: 'my-page',
templateUrl: './my-page.component.html',
styleUrls: ['./my-page.component.css']
})
export class MyPageComponent {
@ViewChild('barChart') barChart: ElementRef;
constructor() {}
ngOnInit() {
console.log(this.barChart)
if (this.barChart) {
console.log(this.barChart.nativeElement.getBoundingClientRect())
}
};
ngAfterViewInit() {
console.log(this.barChart)
if (this.barChart) {
console.log(this.barChart.nativeElement.getBoundingClientRect())
}
};
ionViewDidEnter() {
console.log(this.barChart)
if (this.barChart) {
console.log(this.barChart.nativeElement.getBoundingClientRect())
}
};
}