Clifton Labrum
Clifton Labrum

Reputation: 14068

Get Dataset Values from Chart JS onHover in Version 3

I'm using Chart JS version 3.5.1, and I can't get the onHover function to work. My goal is to have the user hover or a data point, and then have the dataset values available to me inside the onHover.

Here's my setup:

var context = document.getElementById('canvas').getContext('2d')

var options = {
  onHover: function(evt) {
    console.log(evt)
    
    var item = myChart.getElementAtEvent(evt)
    console.log(item)
  },
  interaction: {
    mode: 'index',
    intersect: false,
  },
  plugins: {
    legend: {
      display: false,
    }
  },
  responsive: true,
  maintainAspectRatio: false
}

var myChart = new Chart(context, {
  type: 'line',
  data: {
    labels: obj.labels,
    datasets: [...]
  },
  options: options
})

I'm getting and error on this line:

var item = myChart.getElementAtEvent(evt)

The error says:

myChart.getElementAtEvent is not a function

I have confirmed that myChart is an object, but there doesn't appear to be a getElementAtEvent function.

I also tried the example in the docs here:

const canvasPosition = Chart.helpers.getRelativePosition(e, chart);

// Substitute the appropriate scale IDs
const dataX = chart.scales.x.getValueForPixel(canvasPosition.x);
const dataY = chart.scales.y.getValueForPixel(canvasPosition.y);

But it says:

Cannot read property 'getValueForPixel' of undefined

Does anyone know how I can successfully use onHover with version 3.5.1 of Chart JS?

Upvotes: 1

Views: 1917

Answers (1)

LeeLenalee
LeeLenalee

Reputation: 31371

You are using chart.js v3, in v3 there is no getElementAtEvent, it has been replaced with getElementsAtEventForMode. You can use this to get the active elements but you can also use the second argument the onHover function recieves which is an array with all the active elements:

var options = {
  type: 'line',
  data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        borderColor: 'pink'
      },
      {
        label: '# of Points',
        data: [7, 11, 5, 8, 3, 7],
        borderColor: 'orange'
      }
    ]
  },
  options: {
    onHover: (evt, activeEls, chart) => {
      if (activeEls.length === 0 || chart.getElementsAtEventForMode(evt, 'nearest', {
          intersect: true
        }, true).length === 0) {
        return;
      }

      console.log('Function param: ', activeEls[0].index);
      console.log('lookup with the event: ', chart.getElementsAtEventForMode(evt, 'nearest', {
        intersect: true
      }, true)[0].index);

      activeEls.forEach(point => {
        console.log('val: ', chart.data.datasets[point.datasetIndex].data[point.index])
      })
    }
  }
}

var ctx = document.getElementById('chartJSContainer').getContext('2d');
new Chart(ctx, options);
<body>
  <canvas id="chartJSContainer" width="600" height="400"></canvas>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.1/chart.js"></script>
</body>

Upvotes: 2

Related Questions