Create multiple dynamic charts
Solution 1
In your
canvas ... add a #yourId
(example : canvas *ngFor="let chart of charts; let i = index" id="canvas{{i}} #yourId")
Then you can use @ViewChildren('yourId') myCharts: any; (you can't use myCharts in ngOnInit, only in ngAfterViewInit and after) which will give you your array of charts.
I won't provide much more detail but you can use what's inside your myCharts (use a console.log(myCharts) to see in detail what's in there), you can use this to change data and so on.
Hope this helps.
Solution 2
Here is one of the possible implementations of the previously proposed solution. I created an array called "charts", which will contain as many elements as charts I want to create. Each element of this array has an identifier and the key where we will place the chart later (AfterViewInit).
HTML:
<div>
<canvas *ngFor="let chart of charts; let i = index" id="mychart{{i}}" #mycharts>{{chart.chart}}</canvas>
</div>
.TS:
import {Component, OnInit, Input, AfterViewInit, ViewChildren} from '@angular/core';
import { Chart } from 'chart.js';
// ...
@ViewChildren('mycharts') allMyCanvas: any; // Observe #mycharts elements
charts: any; // Array to store all my charts
constructor() {
this.charts = [
{
"id": "1", // Just an identifier
"chart": [] // The chart itself is going to be saved here
},
{
"id": "2",
"chart": []
},
{
"id": "3",
"chart": []
}
]
}
ngAfterViewInit() {
let canvasCharts = this.allMyCanvas._results; // Get array with all canvas
canvasCharts.map((myCanvas, i) => { // For each canvas, save the chart on the charts array
this.charts[i].chart = new Chart(myCanvas.nativeElement.getContext('2d'), {
// ...
}
})
}
Arad Gonen
Updated on June 19, 2022Comments
-
Arad Gonen almost 2 years
i'm developing a web application - MEAN stack. i'm trying to use ChartJS doughnut chart but i need it to be completely dynamic - first, the number of charts is dynamic (each chart represent something else) so sometimes it will be 3 and sometime 20. second, i want ti be able to access each of the charts for real-time data changing. does it even possible? i tried to create an array that will hold each of the charts data and use *ngFor to create each chart an canvas element but it didn't work.
my chartjs.component.ts:
import { Component, OnInit } from '@angular/core'; import { DataService } from '../data.service'; import { Chart } from 'chart.js'; import { pieceLabel } from 'chart.piecelabel.js'; import {ElementRef} from '@angular/core'; @Component({ selector: 'app-chartjs', templateUrl: './chartjs.component.html', styleUrls: ['./chartjs.component.css'] }) export class ChartjsComponent implements OnInit { constructor( private _dataService : DataService, private elementRef: ElementRef) { } jsons: any; NumberOfSystems: Number; charts = []; ngOnInit() { this._dataService.getData().subscribe(data => { this.jsons = data this.NumberOfSystems = this.jsons.data[0][1].systems.length this.createChartsData() }); } createChartsData() { var array=[]; for(var i =0; i<this.NumberOfSystems;i++) { var pie ={ type: 'doughnut', data: { labels: ["Disks", "Mgmt", "Hardware", "FC", "Vols&Pols"], datasets: [ { backgroundColor:["#008000","#008000","#008000","#008000","#008000"], data: [20,20,20,20,20] } ] }, options: { title: { display: false }, animations: true, tooltips: { enabled: true }, legend: { display: true } } }; array.push(pie); } this.createCharts(array); } createCharts(pieData){ for(var j = 0; j<this.NumberOfSystems;j++) { let htmlRef = this.elementRef.nativeElement.select(`#canvas`+j); console.log(htmlRef); var tempChart = new Chart(htmlRef,pieData[j]); this.charts.push(tempChart); } } }
and this is the chartjs.component.html:
<div> <canvas *ngFor="let chart of charts; let i = index" id="canvas{{i}}">{{charts}}</canvas> </div>
in this state, the ElementRef is null.