0

I have three charts to display for three different services. SO creating array of charts and pushing each newly created chart.
Here is my code.

      import Chart from 'chart.js;
      public charts: any;
      canvas: any;
      ctx: any;

      this.canvas = document.getElementById(serviceChart) as HTMLCanvasElement;
      this.ctx = this.canvas.getContext('2d');
        
    
      this.charts.push(new Chart(this.ctx, {
            // The type of chart we want to create
            type: 'bar',
            // The data for our dataset
            data: barChartDataCollection,
            // Configuration options go here
            options: this.barChartOptions
        }));

I am getting Canvas is already in use. Chart with ID '0' must be destroyed before the canvas with ID 'idpService' can be reused. error while creating new chart and pushing into array. Do i need to destroy each chart after creating it? If yes, How? and where to destroy it? If not, then what is the solution? Please help!

The data which I am getting from api is:

[ { "timestamp": ":2023-04-18", "status": null, "majorVersion": "0", "minorVersion": "74", "statusCodes": [], "receivedPackets": 8640, "expectedPackets": 8640, "received": 100, "lost": 0 }, { "timestamp": ":2023-04-20", "status": null, "majorVersion": "0", "minorVersion": "74", "statusCodes": [], "receivedPackets": 8639, "expectedPackets": 8640, "received": 99, "lost": 1 }, { "timestamp": ":2023-04-24", "status": null, "majorVersion": "0", "minorVersion": "74", "statusCodes": [], "receivedPackets": 8601, "expectedPackets": 8640, "received": 99, "lost": 1 }, { "timestamp": ":2023-05-11", "status": null, "majorVersion": "0", "minorVersion": "78", "statusCodes": [], "receivedPackets": 8639, "expectedPackets": 8640, "received": 99, "lost": 1 } ]

xoxo
  • 1,248
  • 14
  • 19

2 Answers2

0

If you don't want to see the charts in parallel you can simply destroy the current/topmost chart:

(this.charts[this.charts.length - 1] as Chart|undefined)?.destroy();

this.charts.push(new Chart( ......

If you are willing to destroy the chart object, then it makes little sense to keep all charts in an array, it would suffice to keep only the current chart object.

Also, in this case, of sequential charts, it is almost always possible and simpler to just change the data and options of the current chart and call its .update() method to display the next one, so you don't destroy and recreate it.

Another option is to create a new canvas for each chart, that would allow the charts to be displayed in parallel. A simplified version would be

const serviceCanvas = document.getElementById('serviceChart') as HTMLCanvas;
if(this.charts.length > 0){
   this.canvas = document.createElement('canvas');
   serviceCanvas.parentNode!.appendChild(this.canvas);
}
else{
    this.canvas = serviceCanvas;
}
kikon
  • 3,670
  • 3
  • 5
  • 20
  • this gives following error. ERROR Error: NG01203: No value accessor for form control unspecified name attribute. Find more at https://angular.io/errors/NG01203 – xoxo May 15 '23 at 10:07
  • 1
    Which one, I proposed three solutions in my answer. In any case, I can't debug a code I don't have. The three variants I proposed are just sketches corresponding to the code fragment you posted. Please put your functioning (except the error) code (or a part of it that should work except the error) on a codesandbox or stackblitz or similar, and then a full working and tested solution can be provided. – kikon May 16 '23 at 08:31
  • https://stackblitz.com/edit/angular-chart-js-sxajee?file=src/app/app.component.ts – xoxo May 16 '23 at 11:12
  • I have added my code in stackblitz. It not completely working as I am unable to resolve few packages issues. If you can please look into the issue that will be a great help. I am stuck in this from past 1 week. – xoxo May 16 '23 at 11:13
  • Hi kikon, Thanks for your effort. But my issue got resolved. I have posted it above. – xoxo May 16 '23 at 12:25
  • OK then, great! – kikon May 16 '23 at 12:33
0

Finally I found an answer.

I needed to initialize the ctx this way:

  let ctx: CanvasRenderingContext2D = canvas.getContext("2d")!; // <--

Now I am able to display all the charts in parallel.

xoxo
  • 1,248
  • 14
  • 19