Destroy chart.js bar graph to redraw other graph in same <canvas>

I am using the Chart.js library to draw a bar graph, it is working fine, but now I want to destroy the bar graph and make a line graph in the same canvas. I have tried these two ways to clear the canvas:

var grapharea = document.getElementById("barChart").getContext("2d");

grapharea.destroy();

var myNewChart = new Chart(grapharea, { type: 'radar', data: barData, options: barOptions });

second way:

var grapharea = document.getElementById("barChart").getContext("2d");

grapharea.clear();

var myNewChart = new Chart(grapharea, { type: 'radar', data: barData, options: barOptions });

Am I calling it right? OnButtonClick I call this function which uses the same canvas.

Answers:

Answer

The correct method to use, in order to be able to draw another chart on the same canvas, is .destroy(). You must call it on the previously created chart object. You may also use the same variable for both charts.

var grapharea = document.getElementById("barChart").getContext("2d");

var myChart = new Chart(grapharea, { type: 'bar', data: barData, options: barOptions });

myChart.destroy();

myChart = new Chart(grapharea, { type: 'radar', data: barData, options: barOptions });

Straight from the docs (under Prototype Methods):

.destroy()

Use this to destroy any chart instances that are created. This will clean up any references stored to the chart object within Chart.js, along with any associated event listeners attached by Chart.js. This must be called before the canvas is reused for a new chart.

// Example from the docs
var myLineChart = new Chart(ctx, config);
// Destroys a specific chart instance
myLineChart.destroy();

It explicitly states that this method must be called before the canvas can be reused for a new chart.

.clear() is also mentioned later in the same section as the function that "will clear the chart canvas. Used extensively internally between animation frames, but you might find it useful." The chart will be alive and well after calling this method, so this is not the method to call, if you want to reuse the canvas for a brand new chart.

To be honest, though, in cases like yours, I have often used a container div to wrap my canvas and, whenever I needed to create a new chart, I placed a new canvas element in this div. I then used this newly created canvas for the new chart. If you ever come across strange behavior, possibly related to charts occupying the canvas before the current chart, have this approach in mind too.

Answer

Remove the canvas after every chart call, this worked for me

$("canvas#chartreport").remove();
$("div.chartreport").append('<canvas id="chartreport" class="animated fadeIn" height="150"></canvas>');
var ctx = document.getElementById("chartreport").getContext("2d");
chartreport= new Chart(ctx, { .... });
Answer

For ChartJS v2.x you can use update() to update the chart data without explicitly destroying and creating the canvas.

var chart_ctx = document.getElementById("chart").getContext("2d");

var chart = new Chart(chart_ctx, {
    type: "pie",
    data: {}
    options: {}
});

$.ajax({
    ...
}).done(function (response) {
    chart.data = response;
    chart.update();
});
Answer

Maybe there was a better way, but no answers were suited to me.

document.querySelector("#chartReport").innerHTML = '<canvas id="myChart"></canvas>';

my HTML part is

<div class="col-md-6 col-md-offset-3">
     <div id="chartReport">
         <canvas id="myChart"></canvas>
     </div>
</div>
Answer

I'm using Chart.js 2.7.2 as of right now. In my app, I'm creating multiple charts and needed a way to access them to properly "replace" their data and fix the "old chart" showing on hover. None of the answers I've tried worked right.

Here's a way to manage this with one or multiple charts:

Store charts in global

var charts=[]; // global

Function to create charts

function createChart(id, type, labels, data)
{
    // for multiple datasets
    var datasets=[];
    data.forEach(function(set) {
        datasets.push({
            label: set.label,
            data: set.data
        });
    });  

    var config = {
        type: type,
        data: {
            labels: labels,
            datasets: datasets
        }
    };

    if(typeof charts[id] == "undefined") // see if passed id exists
    {   
        // doesn't, so create it
        charts[id]= new (function(){
            this.ctx=$(id); // canvas el
            this.chart=new Chart(this.ctx, config);
        })();     
        console.log('created chart '+charts[id].chart.canvas.id);     
    }
    else
    {
        charts[id].chart.destroy(); // "destroy" the "old chart"
        charts[id].chart=new Chart(charts[id].ctx, config); // create the chart with same id and el
        console.log('replaced chart '+charts[id].chart.canvas.id);        
    }
    // just to see all instances
    Chart.helpers.each(Chart.instances, function(instance){
        console.log('found instance '+instance.chart.canvas.id)
    })

}

For each of your canvas elements like:

<canvas id="thiscanvasid"></canvas>

Use the function to create/replace the chart

createChart('#thiscanvasid', 'bar', json.labels, json.datasets);
Answer

you can test this

 $('#canvas').replaceWith($('<canvas id="canvas" height="320px"></canvas>'));

;)

Answer

In order to solve this problem I have used jQuery's add() and remove() methods, to clear the canvas. I am removing the component and before drawing it again I am appending the canvas again with the same id using jQuery's append() method.

redraw(){

 $("#myChart").remove();// removing previous canvas element
 //change the data values or add new values for new graph
 $("#chart_box").after("<canvas id='myChart'></canvas>");
 // again adding a new canvas element with same id
 generateGraph();// calling the main graph generating function 

}
Answer

I always use only 1 graph/page. Destroy() solved the issues.

 if (
        window.myLine !== undefined
        &&
        window.myLine !== null
    ) {
        window.myLine.destroy();
    }

    window.myLine = new Chart(graphCanvasCtx, config);
Answer

Simple edit for 2020:

This worked for me. Change the chart to global by making it window owned (Change the declaration from var myChart to window myChart)

Check whether the chart variable is already initialized as Chart, if so, destroy it and create a new one, even you can create another one on the same name. Below is the code:

if(window.myChart instanceof Chart)
{
    window.myChart.destroy();
}
var ctx = document.getElementById('myChart').getContext("2d");

Hope it works!

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.