1

What is the proper way to update a bar chart (chartJS) using new data?

With this code below, I can get bar graph to update with new data. But with closer inspection, it looks like the updated graph is on top of the original. When I hover my mouse on the graph, it is jumping back and forth between the old and the new. I am having a hard time understanding the docs..

Maybe it is my HTML?

HTML:

<div>
    <form id="frm2">
        <h7> filter by dates </h7>
        <input type="button" onclick="runGraphButton(updatedCountList, updatedDayCount)" value="update graph">
    </form>
</div>

<div class="chartleft">
    <div id = "buildCountInfo-js">To:</div>
    <canvas id="buildCount"></canvas>
</div>

.js

//intial data
let countList = [3,4,5,4,37,8,4];
let dayCount = [1,1,3,4,5,3,2];

//updated data
let updatedCountList = [3,4,5,4,37,8,4,6,4,7,8,5];
let updatedDayCount = [1,1,3,4,5,3,2,4,5,4,3,2];

//run at page load
runGraph(countList, dayCount);

//run at button push
function runGraphButton(updatedCountList, updatedDayCount){
    runGraph(updatedCountList,updatedDayCount);
}

function runGraph(counts,days){
let ctx = document.getElementById("buildCount").getContext('2d');
let myChart = new Chart(ctx, {
    type: 'bar',
    data: {
        labels: counts,
        datasets: [{
            label: 'Builds per Day',
            data: days,
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255,99,132,1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {stepSize: 1,
                     beginAtZero:true
                }
            }]
        }
    }

});

removeData(myChart);
function removeData(chart) {
    chart.data.labels.pop();
    chart.data.datasets.forEach((dataset) => {
        dataset.data.pop();
    });
    chart.update();
}
}
1
  • edited .js to fix mistake Commented Feb 13, 2019 at 2:47

2 Answers 2

1

chart.destroy() will 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.

So if you want to load a completely new dataset, you could call chart.destroy() beforehand. I refactored your code a little bit and this seems to be working:

let myChart; // declare chart variable

//intial data
let countList = [3, 4, 5, 4, 37, 8, 4];
let dayCount = [1, 1, 3, 4, 5, 3, 2];

//updated data
let updatedCountList = [3, 4, 5, 4, 37, 8, 4, 6, 4, 7, 8, 5];
let updatedDayCount = [1, 1, 3, 4, 5, 3, 2, 4, 5, 4, 3, 2];

//run at page load
myChart = runGraph(countList, dayCount);

//run at button push
function runGraphButton(updatedCountList, updatedDayCount) {
  myChart.destroy();  // call destroy before loading new dataset
  myChart = runGraph(updatedCountList, updatedDayCount);
}

function runGraph(counts, days) {
  let ctx = document.getElementById("buildCount").getContext('2d');
  let myChart = new Chart(ctx, {
    type: 'bar',
    data: {
      labels: counts,
      datasets: [{
        label: 'Builds per Day',
        data: days,
        backgroundColor: [
          'rgba(255, 99, 132, 0.2)',
          'rgba(54, 162, 235, 0.2)',
          'rgba(255, 206, 86, 0.2)',
          'rgba(75, 192, 192, 0.2)',
          'rgba(153, 102, 255, 0.2)',
          'rgba(255, 159, 64, 0.2)'
        ],
        borderColor: [
          'rgba(255,99,132,1)',
          'rgba(54, 162, 235, 1)',
          'rgba(255, 206, 86, 1)',
          'rgba(75, 192, 192, 1)',
          'rgba(153, 102, 255, 1)',
          'rgba(255, 159, 64, 1)'
        ],
        borderWidth: 1
      }]
    },
    options: {
      scales: {
        yAxes: [{
          ticks: {
            stepSize: 1,
            beginAtZero: true
          }
        }]
      }
    }

  });
  return myChart; // return chart object
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<div>
  <form id="frm2">
    <h7> filter by dates </h7>
    <input type="button" onclick="runGraphButton(updatedCountList, updatedDayCount)" value="update graph">
  </form>
</div>

<div class="chartleft">
  <div id="buildCountInfo-js">To:</div>
  <canvas id="buildCount"></canvas>
</div>

Note I also removed the removeData() method since I'm calling destroy().

Sign up to request clarification or add additional context in comments.

1 Comment

That did it! Thank you the answer from @adlanArifZakaria seems to work also, but just a few more lines of code. Not sure of the benefit of one over the other? Either way the solutions work. Thanks again guys.
1

Just change your update function to be

//run at button push
function runGraphButton(updatedCountList, updatedDayCount){
    chart.data.labels = updatedCountList;
    chart.data.datasets[0].data = updatedDayCount;
    chart.update();
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.