Create multiple dynamic charts

13,079

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'), {
        // ...
      }
   })
 }
Share:
13,079
Arad Gonen
Author by

Arad Gonen

Updated on June 19, 2022

Comments

  • Arad Gonen
    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.