Chart.js: Dynamic Changing of Chart Type (Line to Bar as Example)
Asked Answered
R

8

17

I am trying to hot swap chart types based on select box changes. If data needs to be updated, it changes.

So for example, on page load I create a chart like this:

var config = {
     type: 'line',
     data: {
        labels: this.labels,
        datasets: [{
            label: 'Some Label',
            data: this.values
        }]
     },
     options: {
         responsive: true
     }
}
var context = document.getElementById('canvas').getContext('2d');
window.mychart = new Chart(context, config);

But then I change the combo box to a bar chart. I have tested the data with bar chart on page load, and it worked great.

Here's how I am trying to change the chart.

window.mychart.destroy();

// chartType = 'bar'
config.type = chartType;

var context = document.getElementById('canvas').getContext('2d');
window.mychart = new Chart(context, config);

window.mychart.update();
window.mychart.render();

But nothing happens. The line chart remains. How can I dynamically change the chart type? (Even if it means destroying & re-creating the chart canvas).

UPDATE

Note it looks like it is actually destroying the chart, but keeps redrawing a line chart, even though I do console.log(config.type); and it returns bar, not line

Revanche answered 30/4, 2016 at 0:19 Comment(0)
F
24

The Fix

  • Destroy the old chart (to remove event listeners and clear the canvas)
  • Make a deep copy of the config object
  • Change the type of the copy
  • Pass the copy instead of the original object.

Here is a working jsfiddle example

Example Overview:

var temp = jQuery.extend(true, {}, config);
temp.type = 'bar'; // The new chart type
myChart = new Chart(ctx, temp);

NOTE: Using version 2.0.1 of Chart.js

Why this works

Chart.js modifies the config object you pass in. Because of that you can not just change 'config.type'. You could go into the modified object and change everything to the type you want, but it is much easier to just save the original config object.

Frohman answered 2/5, 2016 at 17:59 Comment(1)
Thanks for this. I found that this is an unexpected bug in 2.0 right now and will be fixed in the next release. But your deep copy solution works in the short term.Revanche
P
8

Just to follow up that this is now fixed in v.2.1.3, as followed through by https://stackoverflow.com/users/239375/nathan

document.getElementById('changeToLine').onclick = function() {
  myChart.destroy();
  myChart = new Chart(ctx, {
    type: 'line',
    data: chartData
  });
};

Confirmed fixed in latest version. Check out http://codepen.io/anon/pen/ezJGPB and press the button under the chart to change it from a bar to a line chart.

Pampero answered 25/12, 2016 at 7:56 Comment(1)
this works, but it would be great if we can just pass a chart type we want to render not the data part.Equidistance
E
6

In chart.js 3.8.0 you can do it like this:


let chart = new Chart(ctx, {
  type: "line",
  data: {
    // ...
  },
  options: {
    // ...
  }
});

chart.config.type = "bar";
chart.update();

you can also change data and options this way

chart.js docs on updating: https://www.chartjs.org/docs/latest/developers/updates.html

codepen example: https://codepen.io/3zbumban/pen/yLKMMJx

Ephemeral answered 3/6, 2022 at 14:0 Comment(6)
You can change data and options but chart type (!== dataset.type) is config and you cannot change it.Microcosm
@PavelFrancírek it does work perfectly for me when switching between bar and line chart type. see: codepen.io/3zbumban/pen/yLKMMJxEphemeral
If you use "pie" instead of "bar" type chart.config.type = chart.config.type === "line" ? "pie" : "line" pie is shown but rest (axes, rulers etc.) stays of original type.Microcosm
@PavelFrancírek there is a simple reason and solution for this. I set Options that configure the scales. If you remove these when changing the chart type to pie it works. see: codepen.io/3zbumban/pen/YzaZJEe if you need further help you can contact me. Also pie charts and line/bar charts are for very different types of visualizations so it's most of the time not necessary to switch between them. (for example timeseries data)Ephemeral
Oh, I see. I didn't realize that options don't reset when changing type. Thank you for clarification.Microcosm
This approach should be marked as hack. You can't change conifg propery since its intended to be readonly. Evenmore config may not have type at all, because type is determined per dataset and config.type is just fallback.Shaman
F
3

No need to destroy and re-create, you just have to change the type from the chart's config variable then update the chart.

var chartCfg = {
    type: 'pie',
    data: data
};

var myChart = new Chart(ctx, chartCfg );

function changeToBar() {
    chartCfg.type = "bar";
    myChart.update();
}
Faircloth answered 16/7, 2021 at 14:24 Comment(0)
D
1

The alternate solution can be as simple as creating both the charts in separate Div elements. Then as per your condition just make one visible and hide other in the javascript. This should serve the purpose you may have for changing the chart type for your requirement.

Drillstock answered 30/4, 2016 at 2:24 Comment(2)
I am trying to experiment with a "chart builder" of sorts. Choose chart type, then data sources, and so on. So essentially I only want one chart type on the page, and want to swap them in and out as necessary.Revanche
One solution I can think of is to have different Div templates, with separate elements for different chart types. Then in the area where you want to display your chart, have a main parent Div element. Based on the selection of the chart type, you can add/remove child Div element corresponding to the chart type selected. I believe you will get better performance too this way.Drillstock
F
1

In ChartJS, the chart type can also be changed easily like chart data. Following example might be helpful

        my_chart.type = 'bar';
        my_chart.update();
Ferdinana answered 26/3, 2021 at 10:18 Comment(1)
I could not get this method to work. updating other parameters worked while updating type did not.Sway
H
0

In ChartJS 3, :

var options = // your options.
var data = { ...myChart.data }; // deep copy of the data
var ctx = document.getElementById('myChart_id').getContext('2d');

myChart.destroy()

/// Modify ctx or data if you need to.

myChart = new Chart(ctx, {
        type: chart_type,
        data: data
});

Chart.options = options;
myChart.update();
Hamadryad answered 16/10, 2021 at 20:31 Comment(0)
K
0

Its 2024 and I am working on a Legacy Project so I am using Chart.js v2.7.2. If you are starting a new project use the current version. This is what worked for me

//in my adjax beforesend function
beforeSend: function(){
    helper.btnLoading(btn);
    //remove the canvas element entirely
    $("#chartResultWrapper").remove();
},

//in my adjax success function
success: function(response){
  let data = response.result;
  
  //add the canvas element to the dom with your targetted ID
  $("#resultsBody").prepend('<canvas id="chartResultWrapper"></canvas>');

  createChart(response.result, type);
},
<div class="card-body" id="resultsBody">
        <canvas id="chartResultWrapper"></canvas>
        <div class="mt-4" id="mainResult">
      <small class="text-muted">No data available</small>
    </div>
</div>

The rest of your code should remain same. Hopes it works for your case

Kamkama answered 4/3 at 17:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.