chart.js load totally new data
Asked Answered
F

24

102

The API for chart.js allows one to edit points of the datasets loaded into it, for example:

.update( )

Calling update() on your Chart instance will re-render the chart with any updated values, allowing you to edit the value of multiple existing points, then render those in one animated render loop.

.addData( valuesArray, label )

Calling addData(valuesArray, label) on your Chart instance passing an array of values for each dataset, along with a label for those points.

.removeData( )

Calling removeData() on your Chart instance will remove the first value for all datasets on the chart.

All of these are great, but I cannot figure out how to load an entirely new dataset in, wiping out the old. The documentation does not seem to cover this.

Flittermouse answered 16/7, 2014 at 16:15 Comment(0)
W
116

I had huge problems with this

First I tried .clear() then I tried .destroy() and I tried setting my chart reference to null

What finally fixed the issue for me: deleting the <canvas> element and then reappending a new <canvas> to the parent container


There's a million ways to do this:

var resetCanvas = function () {
  $('#results-graph').remove(); // this is my <canvas> element
  $('#graph-container').append('<canvas id="results-graph"><canvas>');
  canvas = document.querySelector('#results-graph'); // why use jQuery?
  ctx = canvas.getContext('2d');
  ctx.canvas.width = $('#graph').width(); // resize to parent width
  ctx.canvas.height = $('#graph').height(); // resize to parent height

  var x = canvas.width/2;
  var y = canvas.height/2;
  ctx.font = '10pt Verdana';
  ctx.textAlign = 'center';
  ctx.fillText('This text is centered on the canvas', x, y);
};
Wallasey answered 31/7, 2014 at 16:14 Comment(2)
This answer works, but I found destroy also works in the latest version. Recommended on this post - github.com/nnnick/Chart.js/issues/559Swayback
it would help the empty the graph-container div to remove old iframes $('#results-graph').remove(); $('#graph-container').empty(); $('#graph-container').append('<canvas id="results-graph"><canvas>');Undesigned
C
81

You need to destroy:

myLineChart.destroy();

Then re-initialize the chart:

var ctx = document.getElementById("myChartLine").getContext("2d");
myLineChart = new Chart(ctx).Line(data, options);
Coruscation answered 17/11, 2014 at 22:34 Comment(2)
just use it like this if(window.myLine){ window.myLine.destroy(); } OR if(myLineChart){ myLineChart.destroy(); }Semanteme
Can confirm destroying then re-initialising doesn't cause any flickering and looks like the data points were dynamically updatedBrainard
M
52

With Chart.js V2.0 you can to do the following:

websiteChart.config.data = some_new_data;
websiteChart.update();
Moribund answered 29/4, 2016 at 18:51 Comment(2)
Exactly what the op asked for.Candice
When I do chart.config.data = newData, I have this error: TypeError: undefined is not an object (evaluating 'i.data.datasets.length') Someone have the same issue?Mufti
W
27

It is an old thread, but in the current version (as of 1-feb-2017), it easy to replace datasets plotted on chart.js:

suppose your new x-axis values are in array x and y-axis values are in array y, you can use below code to update the chart.

var x = [1,2,3];
var y = [1,1,1];

chart.data.datasets[0].data = y;
chart.data.labels = x;

chart.update();
Wyly answered 1/2, 2017 at 13:44 Comment(3)
Thanks a ton, Man! Wasted all day. Finally stumbled upon your answer. Thank you.Acerbity
This was helpful and worked for me. Even just using [] to set an empty dataset, and then doing a new "push" will do the trick as well.Reciprocation
I had the same problem, but I found this answer useful. It works for me!Moussorgsky
C
18

ChartJS 2.6 supports data reference replacement (see Note in update(config) documentation). So when you have your Chart, you could basically just do this:

myChart.data.labels = ['1am', '2am', '3am', '4am'];
myChart.data.datasets[0].data = [0, 12, 35, 36];
myChart.update();

It doesn't do the animation you'd get from adding points, but existing points on the graph will be animated.

Charpoy answered 5/10, 2017 at 13:58 Comment(0)
M
12

My solution to this is pretty simple. (VERSION 1.X)

getDataSet:function(valuesArr1,valuesArr2){
        var dataset = [];
        var arr1 = {
            label: " (myvalues1)",
            fillColor: "rgba(0, 138, 212,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(0, 138, 212,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: valuesArr1
        };
        var arr2 = {
            label: " (myvalues2)",
            fillColor: "rgba(255, 174, 087,0.5)",
            strokeColor: "rgba(220,220,220,0.8)",
            highlightFill: "rgba(255, 174, 087,0.75)",
            highlightStroke: "rgba(220,220,220,1)",
            data: valuesArr2
        };
        /*Example conditions*/
        if(condition 1)
          dataset.push(arr1);
        }
        if(condition 2){
          dataset.push(arr1);
          dataset.push(arr2);
        }

        return dataset;
    }

var data = {
    labels: mylabelone,
    datasets: getDataSet()
};
if(myBarChart != null) // i initialize myBarChart var with null
    myBarChart.destroy(); // if not null call destroy
    myBarChart = new Chart(ctxmini).Bar(data, options);//render it again ...

No flickering or problems. getDataSet is a function to control what dataset I need to present

Mindexpanding answered 18/1, 2016 at 10:36 Comment(2)
Can you add the code snippet of getDataSet() as well?Mattox
Added the getDataSet() exampleMindexpanding
F
8

I answered this here see How to clear a chart from a canvas so that hover events cannot be triggered?

But here is the solution:

var myPieChart=null;

function drawChart(objChart,data){
    if(myPieChart!=null){
        myPieChart.destroy();
    }
    // Get the context of the canvas element we want to select
    var ctx = objChart.getContext("2d");
    myPieChart = new Chart(ctx).Pie(data, {animateScale: true});
}
Footworn answered 5/6, 2015 at 23:19 Comment(0)
G
6

According to docs, clear() clears the canvas. Think of it as the Eraser tool in Paint. It has nothing to do with the data currently loaded in the chart instance.

Destroying the instance and creating a new one is wasteful. Instead, use API methods removeData() and addData(). These will add/remove a single segment to/from the chart instance. So if you want to load completely new data, just loop a chart data array, and call removeData(index) (array indexes should correspond to current segment indexes). Then, use addData(index) to fill it with the new data. I suggest wrapping the two methods for looping the data, as they expect a single segment index. I use resetChart and updateChart. Before continuing, make sure you check Chart.js latest version and documentation. They may have added new methods for replacing the data completely.

Gentoo answered 18/11, 2015 at 18:56 Comment(3)
I like your answer and its consistent with the information I have been reading online. If you are able to show and example that would be really helpful. The two examples that I have seen online that are similar are: jsbin.com/yitep/5/edit?html,js,output and jsbin.com/yitep/4/edit?html,js,outputBrennabrennan
The only problem is that updating a chart becomes extremely cumbersome and super slow if you have to replace the chart data with essentially a completely different dataset. For starters, I have not found a way to update existing x-axis labels. Destroying and reinstantiating the entire chart is the only real solution in such circumstances.Pessa
Unfortunately, I only dealt with a Doughnut chart, which is less complex. Did you check out the latest API?Gentoo
S
5

None of the above answers helped my particular situation in a very clean way with minimal code. I needed to remove all datasets and then loop to add in several datasets dynamically. So this snipped is for those that make it all the way to the bottom of the page without finding their answer :)

Note: make sure to call chart.update() once you have loaded all of your new data into the dataset object. Hope this helps somebody

function removeData(chart) {
   chart.data.datasets.length = 0;
}

function addData(chart, data) {
  chart.data.datasets.push(data);
}
Sicard answered 31/7, 2017 at 14:19 Comment(0)
N
5

Not is necesary destroy the chart. Try with this

function removeData(chart) {

        let total = chart.data.labels.length;

        while (total >= 0) {
            chart.data.labels.pop();
            chart.data.datasets[0].data.pop();
            total--;
        }

        chart.update();
    }
Ninth answered 20/2, 2020 at 4:59 Comment(0)
S
4

I ran into the same issue, I have 6 pie charts on a page which can all be updated at the same time. I am using the following function to reset chart data.

// sets chart segment data for previously rendered charts
function _resetChartData(chart, new_segments) {
    // remove all the segments
    while (chart.segments.length) {
        chart.removeData();
    };

    // add the new data fresh
    new_segments.forEach (function (segment, index) {
        chart.addData(segment, index);
    });
};

// when I want to reset my data I call
_resetChartData(some_chart, new_data_segments);
some_chart.update();
Sulphate answered 30/9, 2014 at 23:28 Comment(1)
While this works, I found that it’s much slower (due to animation when adding each point) compared to recreating chart altogether.Loney
G
4

I tried neaumusic solution, but later found out that the only problem with destroy is the scope.

var chart;

function renderGraph() {
    // Destroy old graph
    if (chart) {
        chart.destroy();
    }

    // Render chart
    chart = new Chart(
        document.getElementById(idChartMainWrapperCanvas),
        chartOptions
    );
}

Moving my chart variable outside the function scope, got it working for me.

Grain answered 7/5, 2017 at 12:50 Comment(0)
O
3

Please Learn how Chart.js (version 2 here) works and do it for whatever attribute you want:


1.Please suppose you have a bar chart like the below in your HTML:
<canvas id="your-chart-id" height="your-height" width="your-width"></canvas>

2.Please suppose you have a javascript code that fills your chart first time (for example when page is loaded):

var ctx = document.getElementById('your-chart-id').getContext('2d');
var chartInstance = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: your-lables-array,
        datasets: [{
            data: your-data-array,
            /*you can create random colors dynamically by ColorHash library [https://github.com/zenozeng/color-hash]*/
            backgroundColor: your-lables-array.map(function (item) {
                return colorHash.hex(item);
            })
        }]
    },
    options: {
        maintainAspectRatio: false,
        scales: {
            yAxes: [ { ticks: {beginAtZero: true} } ]
        },
        title: {display: true, fontSize: 16, text: 'chart title'},
        legend: {display: false}
    }
});

Please suppose you want to update fully your dataset. It is very simple. Please look at the above code and see how is the path from your chart variable to data and then follow the below path:

  • select chartInstance var.
  • Then select data node inside the chartInstance.
  • Then select datasets node inside the data node.
    (note: As you can see, the datasets node is an array. so you have to specify which element of this array you want. here we have only one element in the datasets node. so we use datasets[0]
  • So select datasets[0]
  • Then select data node inside in the datasets[0].


This steps gives you chartInstance.data.datasets[0].data and you can set new data and update the chart:

chartInstance.data.datasets[0].data = NEW-your-data-array
//finally update chart var:
chartInstance.update();


Note: By following the above algorithm, you can simply achieve to each node you want.
Oxidate answered 11/4, 2020 at 9:51 Comment(0)
R
2

You need to clean old data. No need to re initialize:

for (i in myChartLine.datasets[0].points)
    myChartLine.removeData();
Runge answered 9/1, 2015 at 4:31 Comment(0)
W
2

If anyone is looking for how to do this in React. For a linechart, assuming you have a wrapper component around the chart:

(This assumes you are using v2. You do not need to use react-chartjs. This is using the normal chart.js package from npm.)

propTypes: {
  data: React.PropTypes.shape({
    datasets: React.PropTypes.arrayOf(
      React.PropTypes.shape({

      })
    ),
    labels: React.PropTypes.array.isRequired
  }).isRequired
},
componentDidMount () {
  let chartCanvas = this.refs.chart;

  let myChart = new Chart(chartCanvas, {
    type: 'line',
    data: this.props.data,
    options: {
      ...
    }
  });

  this.setState({chart: myChart});
},
componentDidUpdate () {
    let chart = this.state.chart;
    let data = this.props.data;

    data.datasets.forEach((dataset, i) => chart.data.datasets[i].data = dataset.data);

    chart.data.labels = data.labels;
    chart.update();
},
render () {
  return (
    <canvas ref={'chart'} height={'400'} width={'600'}></canvas>
  );
}

The componentDidUpdate functionality allows you to update, add, or remove any data from the this.props.data.

Wintertime answered 4/5, 2016 at 23:33 Comment(0)
B
2

To keep the chart size from changing after reloading:

responsive: true,
maintainAspectRatio: false

To clear the previous chart:

myChart.destroy();

For example:

HTML:

<canvas id="ChartJs" style="width: 100%; height: 300px;></canvas>

Javascript:

var myChart = null;
const config = {
    type: 'line',
    data: DATA,
    options: {
        responsive: true,
        maintainAspectRatio: false
    }
};

if (myChart != null) 
    myChart.destroy();
myChart = new Chart(document.getElementById('MyChart ').getContext('2d'), config);
Bessbessarabia answered 6/9, 2022 at 9:1 Comment(0)
L
2

Pavan gave the right answer; but I would like to expound upon that a bit. This issue plagued me FOREVER when I first got started using ChartJS.

Calling the .update() function on your Chart object is correct. No need to delete the existing chart or do something like removing the canvas element to later append a new one. That works.. but isn't necessary.

Working CodePen: https://codepen.io/vpolston/pen/KKRoEBY

Video walkthrough: https://www.youtube.com/watch?v=Ac5pzmHO3_A

Firstly if you want to know the why then I would recommend doing a console.log(myChart) of your chart object. You'll see all kinds of properties that can be updated by simply assigning it a new value and then calling the myChart.update() on your chart.

Let's say you have a chart that you called myChart when you instantiated it.. this part:

const myChart = new Chart('myChart', {}

The variable name is important. To update the dataset you silo down into what you saw when you console.log'd the chart. So your dataset would be

myChart.config.data.datasets[0].data

Just assign that a new value like this:

const newDatasArray = [1,52,23,23,48];
myChart.config.data.datasets[0].data = newDatasArray;

and then for the labels if you needed to change those:

const newLabelsArray = ["Jan", "Feb", "Mar", "Apr", "May"];
myChart.config.data.labels = newLabelsArray;

And then finally call the update function with myChart.update();

You'll see the chart update to use the new dataset and/or labels.

Hopefully that gives a bit more insight into properly updating a chart. If you have a further question let me know and I'd be glad to try to help.

Thanks, VP

Lower answered 30/9, 2022 at 19:47 Comment(1)
This is the only solution here that helped me, thank you for posting it.Sellma
F
0

The only solution I can find so far for myself is to re-initialize the chart from scratch:

var myLineChart = new Chart(ctx).Line(data, options);

However this seems a bit hokey to me. Any better, more standard solution anybody?

Flittermouse answered 16/7, 2014 at 16:18 Comment(1)
This pretty much works for me except you need to first do myLineChart.destroy() to get rid of the old one or you'll have a flicker as it redraws.Staysail
B
0

I had loads of trouble with this too. I have data and labels in separate arrays then I reinitialise the chart data. I added the line.destroy(); as suggested above which has done the trick

var ctx = document.getElementById("canvas").getContext("2d");
if(window.myLine){
	window.myLine.destroy();
}
window.myLine = new Chart(ctx).Line(lineChartData, {
  etc
  etc
Bootee answered 10/1, 2015 at 11:35 Comment(0)
R
0

There is a way to do this without clearing the canvas or starting over, but you have to man handle the creation of the chart so that the data is in the same format for when you update.

Here is how I did it.

    var ctx = document.getElementById("myChart").getContext("2d");
    if (chartExists) {
        for (i=0;i<10;i++){
            myNewChart.scale.xLabels[i]=dbLabels[i]; 
            myNewChart.datasets[0].bars[i].value=dbOnAir[i];
        }
        myNewChart.update();
      }else{
          console.log('chart doesnt exist');
          myNewChart = new Chart(ctx).Bar(dataNew);
          myNewChart.removeData();
          for (i=0;i<10;i++){
              myNewChart.addData([10],dbLabels[i]);
          }
          for (i=0;i<10;i++){      
              myNewChart.datasets[0].bars[i].value=dbOnAir[i];
          }
          myNewChart.update();
          chartExists=true;
        }

I basically scrap the data loaded in at creation, and then reform with the add data method. This means that I can then access all the points. Whenever I have tried to access the data structure that is created by the:

Chart(ctx).Bar(dataNew);

command, I can't access what I need. This means you can change all the data points, in the same way you created them, and also call update() without animating completely from scratch.

Revegetate answered 1/4, 2016 at 19:55 Comment(0)
T
0

Chart JS 2.0

Just set chart.data.labels = [];

For example:

function addData(chart, label, data) {
    chart.data.labels.push(label);
    chart.data.datasets.forEach((dataset) => {
       dataset.data.push(data);
    });
    chart.update();
}

$chart.data.labels = [];

$.each(res.grouped, function(i,o) {
   addData($chart, o.age, o.count);
});
$chart.update();
Thermoscope answered 16/7, 2019 at 13:22 Comment(0)
D
0

When creating the chart object you need to save the instance in a variable.

var currentChart = new Chart(ctx, ...);

And before loading new data, you need to destroy it:

currentChart.destroy();
Deandreadeane answered 23/10, 2020 at 23:39 Comment(0)
B
0

Firstly, let a variable remember an instance of your chart.

             let yourChart = new Chart(ctxBar, {
                    type: 'bar',
                    data: {
                        labels: labels,
                        datasets: datasets
                    },
                });

Secondly, the thing I mostly struggled with was getting the data structure in the right format before updating the chart. So after looking at the data key structure of chart js object:

  data: {
        labels: ['Jan', 'Feb'],
        datasets: [{
            label: 'Net sales',
            data: data
        }, {
            label: 'Cost of goods sold',
            data: data
        }, {
            label: 'Gross margin',
            data: data
        }]
    }

Notice the data key value is an object consisting of two keys, labels and datasets. labels key' value is an array, while datasets key' value is also an array with an object as value.

Therefore, to remove labels and datasets from a chart instance I used:

yourChart.data.labels = [];
yourChart.data.datasets = [{}];
yourChart.update();

To add labels and datasets to a chart instance I used:

yourChart.data.labels = ['label 1', 'label 2'];
yourChart.data.datasets = [{
                label: 'column lables',
                data: [450, 50],
                backgroundColor: ["#dc3545", "#ffb759"]
            }];
yourChart.update();

Prepare server side
The labels and datasets values can be prepared server side as follows (in my case php):

$datajs = function ($data, $bg_colour) // function emulating chart js datasets key value structure
        {
            return [
                'data' => $data,
                'backgroundColor' => $bg_colour
            ];
        };
$datasets = [];
$labels = ['label 1', 'label 2'];
$datasets[] = $datajs([42,10], ["#dc3545", "#ffb759"]);
$datasets[] = $datajs([100,5], ["#dc3545", "#ffb759"]);

To just replace data from data key value from datasets (I did not test this)

yourChart.data.datasets.forEach((dataset) => {
    dataset.data = [];
});
yourChart.update();
// if you have an array of arrays
let array = [[42,20],[58,68],[78,1]];
let length = yourChart.data.datasets.length;
for (let i = 0; i < array.length; i++) {
    const element = array[i];
    if (i < length) {
        yourChart.data.datasets[i].data = element;
    } else {
        yourChart.data.datasets[] = {data: element};
    }
}
yourChart.update();
Benzel answered 23/4, 2021 at 16:7 Comment(0)
N
0

This did the trick for me

chart.config.data = [];
chart.update();
Nerland answered 23/1 at 13:1 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.