CorneeldH
CorneeldH

Reputation: 593

chart.js tooltip keeps remembering old data after update

I show a chart with chart.js and when a user hovers over it a tooltip is displayed. This works fine.

However, I want to add option that users can un-check data-points. I did and this is done correct, but the tooltip-functionality remembers both the new and the old data. So if you hover over the chart it flickers between old and new.

When I make a custom tooltip and place a console.log of the data-oject I can see that it just loads several data-objects in.

Is there a way to make sure the old data is truly forgotten?

See the fiddle https://jsfiddle.net/CorneelDragon/s0udzwv3/27/ or see code below (It works at the start, but when you uncheck things the tooltip makes it erratic):

<script 
src='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js'></script>`
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>`
<div id="slct2">"beh"</div>
<table id="table1"  border=1></table>
<!-- bar chart canvas element -->
<canvas id="myChart" width="200" height="50"></canvas>
<script type="text/javascript">
</script>

and the javascript:

test_labels = ["meh", "beh", "yeh"]
score = [4,3.8,5]
var s2 = document.getElementById("slct2");
s2.innerHTML = "";
for (var test in test_labels) {
    if (test_labels.hasOwnProperty(test)) {
        var pair = test_labels[test] + score[test];
        var checkbox = document.createElement("input");
        checkbox.type = "checkbox";
        checkbox.name = "test_filter";
        checkbox.value = pair;
        checkbox.checked = true;
        s2.appendChild(checkbox);
        var label = document.createElement('label');
        label.htmlFor = pair;
        label.appendChild(document.createTextNode(pair));
        s2.appendChild(label);
        s2.appendChild(document.createElement("br"));    
    }
}

function fillCanvas (test_labels, score) {
  var ctx = document.getElementById("myChart").getContext('2d');
  ctx.innerHTML = "";

  var myChart = new Chart(ctx, {
      type: 'bar',
      data: {
          labels : ["test_month"]
      },
  });

  setTimeout(function () {

     for (test in test_labels){
        myChart.data.datasets.push({
          backgroundColor: 'rgb(228,26,28)',
          label: test_labels[test],
          data: [score[test]]
        });
      }

    myChart.update();

  }, 1000);

}
fillCanvas(test_labels, score);

var filter_magic = function(e) {

        test_selected = []
        var table1 = document.getElementById("table1");
        table1.innerHTML = "";
        jQuery('input[type="checkbox"][name="test_filter"]').each(function() {
            if (jQuery(this).is(':checked')) {
              var tr = document.createElement('tr');
              tr.innerHTML = this.value;
              table1.appendChild(tr);
              test_selected.push(this.value);
            }
          })
        fillCanvas(test_selected, score);
        }     
jQuery('input[type="checkbox"][name="test_filter"]').on('change', filter_magic);
filter_magic();  

Upvotes: 3

Views: 1871

Answers (1)

Kunal Khivensara
Kunal Khivensara

Reputation: 1669

This is not the right way to update a chart, in your code every time you are updating the chart you are creating a new instance of the chart as well without destroying the previous instance and that is why you can see the old value on hover.

One solution would be if you want to create a new chart every time then store your chart in a global variable and whenever checkbox is toggled then check if the chart is stored in the variable, destroy it then create a new one.

See the below code or fiddle -> https://jsfiddle.net/s0udzwv3/31/

test_labels = ["meh", "beh", "yeh"]
score = [4,3.8,5]
var s2 = document.getElementById("slct2");
s2.innerHTML = "";
for (var test in test_labels) {
    if (test_labels.hasOwnProperty(test)) {
        var pair = test_labels[test] + score[test];
        var checkbox = document.createElement("input");
        checkbox.type = "checkbox";
        checkbox.name = "test_filter";
        checkbox.value = pair;
        checkbox.checked = true;
        s2.appendChild(checkbox);
        var label = document.createElement('label');
        label.htmlFor = pair;
        label.appendChild(document.createTextNode(pair));
        s2.appendChild(label);
        s2.appendChild(document.createElement("br"));    
    }
}
var myChart;

function fillCanvas (test_labels, score) {  
  var ctx = document.getElementById("myChart").getContext('2d');
  ctx.innerHTML = "";

  if(myChart)
  {
    myChart.destroy();
  }

  myChart = new Chart(ctx, {
      type: 'bar',
      data: {
          labels : ["test_month"]
      },
  });

  setTimeout(function () {
     for (test in test_labels){
        myChart.data.datasets.push({
          backgroundColor: 'rgb(228,26,28)',
          label: test_labels[test],
          data: [score[test]]
        });
      }

    myChart.update();

  }, 1000);
}

fillCanvas(test_labels, score);

var filter_magic = function(e) {

        test_selected = []
        var table1 = document.getElementById("table1");
        table1.innerHTML = "";
        jQuery('input[type="checkbox"][name="test_filter"]').each(function() {
            if (jQuery(this).is(':checked')) {
              var tr = document.createElement('tr');
              tr.innerHTML = this.value;
              table1.appendChild(tr);
              test_selected.push(this.value);
            }
          })
        fillCanvas(test_selected, score);
        }     
jQuery('input[type="checkbox"][name="test_filter"]').on('change', filter_magic);
filter_magic();  

And the another recommended way would load the chart only once with the new Chart and every time for the checkbox toggle just push new datasets and call the chart.update() method stored in a global variable.

Upvotes: 5

Related Questions