[javascript] Click events on Pie Charts in Chart.js

I've got a question regard Chart.js.

I've drawn multiple piecharts using the documentation provided. I was wondering if on click of a certain slice of one of the charts, I can make an ajax call depending on the value of that slice?

For example, if this is my data

var data = [
    {
        value: 300,
        color:"#F7464A",
        highlight: "#FF5A5E",
        label: "Red"
    },
    {
        value: 50,
        color: "#46BFBD",
        highlight: "#5AD3D1",
        label: "Green"
    },
    {
        value: 100,
        color: "#FDB45C",
        highlight: "#FFC870",
        label: "Yellow"
    }
], 

is it possible for me to click on the Red labelled slice and call a url of the following form: example.com?label=red&value=300? If yes, how do I go about this?

This question is related to javascript jquery charts chart.js

The answer is


Chart.js 2.0 has made this even easier.

You can find it under common chart configuration in the documentation. Should work on more then pie graphs.

options:{
    onClick: graphClickEvent
}

function graphClickEvent(event, array){
    if(array[0]){
        foo.bar; 
    }
}

It triggers on the entire chart, but if you click on a pie the model of that pie including index which can be used to get the value.


I was facing the same issues since several days, Today i have found the solution. I have shown the complete file which is ready to execute.

<html>
<head><script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.js">
</script>
</head>
<body>
<canvas id="myChart" width="200" height="200"></canvas>
<script>
var ctx = document.getElementById("myChart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
    labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"],
    datasets: [{
        label: '# of Votes',
        data: [12, 19, 3, 5, 2, 3],
        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: {
                beginAtZero:true
            }
        }]
    },
onClick:function(e){
    var activePoints = myChart.getElementsAtEvent(e);
    var selectedIndex = activePoints[0]._index;
    alert(this.data.datasets[0].data[selectedIndex]);


}
}
});
</script>
</body>
</html>

If you are using TypeScript, the code is a little funky because there is no type inference, but this works to get the index of the data that has been supplied to the chart: // events public chartClicked(e:any):void { //console.log(e);

    try {
        console.log('DS ' + e.active['0']._datasetIndex);
        console.log('ID ' +  e.active['0']._index);
        console.log('Label: ' + this.doughnutChartLabels[e.active['0']._index]);
        console.log('Value: ' + this.doughnutChartData[e.active['0']._index]);


    } catch (error) {
        console.log("Error In LoadTopGraph", error);
    }

    try {
        console.log(e[0].active);
    } catch (error) {
        //console.log("Error In LoadTopGraph", error);
    }



}

To successfully track click events and on what graph element the user clicked, I did the following in my .js file I set up the following variables:

vm.chartOptions = {
    onClick: function(event, array) {
        let element = this.getElementAtEvent(event);
        if (element.length > 0) {
            var series= element[0]._model.datasetLabel;
            var label = element[0]._model.label;
            var value = this.data.datasets[element[0]._datasetIndex].data[element[0]._index];
        }
    }
};
vm.graphSeries = ["Series 1", "Serries 2"];
vm.chartLabels = ["07:00", "08:00", "09:00", "10:00"];
vm.chartData = [ [ 20, 30, 25, 15 ], [ 5, 10, 100, 20 ] ];

Then in my .html file I setup the graph as follows:

<canvas id="releaseByHourBar" 
    class="chart chart-bar"
    chart-data="vm.graphData"
    chart-labels="vm.graphLabels" 
    chart-series="vm.graphSeries"
    chart-options="vm.chartOptions">
</canvas>

I have an elegant solution to this problem. If you have multiple dataset, identifying which dataset was clicked gets tricky. The _datasetIndex always returns zero. But this should do the trick. It will get you the label and the dataset label as well. Please note ** this.getElementAtEvent** is without the s in getElement

options: {
   onClick: function (e, items) {
    var firstPoint = this.getElementAtEvent(e)[0];
    if (firstPoint) {
      var label = firstPoint._model.label;
      var val = firstPoint._model.datasetLabel;
      console.log(label+" - "+val);
    }
    
  }
}

If using a Donught Chart, and you want to prevent user to trigger your event on click inside the empty space around your chart circles, you can use the following alternative :

var myDoughnutChart = new Chart(ctx).Doughnut(data);

document.getElementById("myChart").onclick = function(evt){
    var activePoints = myDoughnutChart.getSegmentsAtEvent(evt);

    /* this is where we check if event has keys which means is not empty space */       
    if(Object.keys(activePoints).length > 0)
    {
        var label = activePoints[0]["label"];
        var value = activePoints[0]["value"];
        var url = "http://example.com/?label=" + label + "&value=" + value
        /* process your url ... */
    }
};

Working fine chartJs sector onclick

ChartJS : pie Chart - Add options "onclick"

              options: {
                    legend: {
                        display: false
                    },
                    'onClick' : function (evt, item) {
                        console.log ('legend onClick', evt);
                        console.log('legd item', item);
                    }
                }

Within options place your onclick and call the function you need as an example the ajax you need, I'll leave the example so that every click on a point tells you the value and you can use it in your new function.

    options: {
        plugins: {
            // Change options for ALL labels of THIS CHART
            datalabels: {
                color: 'white',
                //backgroundColor:'#ffce00',
                align: 'start'
            }
        },
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero:true,
                    fontColor: "white"
                },gridLines: {
                        color: 'rgba(255,255,255,0.1)',
                        display: true
                    }
            }],
            xAxes: [{
                ticks: {
                    fontColor: "white"
                },gridLines: {                        
                        display: false
                    }
            }]
        },
        legend: {
        display: false

    },
    //onClick: abre     
        onClick:function(e){ 
    var activePoints = myChart.getElementsAtEvent(e); 
    var selectedIndex = activePoints[0]._index; 
    alert(this.data.datasets[0].data[selectedIndex]); 


} 
    }

  var ctx = document.getElementById('pie-chart').getContext('2d');
 var myPieChart = new Chart(ctx, {
                // The type of chart we want to create
                type: 'pie',

            });

             //define click event
  $("#pie-chart").click(
            function (evt) {
                var activePoints = myPieChart.getElementsAtEvent(evt);
                var labeltag = activePoints[0]._view.label;

                      });

Using Chart.JS version 2.1.3, answers older than this one aren't valid anymore. Using getSegmentsAtEvent(event) method will output on console this message:

getSegmentsAtEvent is not a function

So i think it must be removed. I didn't read any changelog to be honest. To resolve that, just use getElementsAtEvent(event) method, as it can be found on the Docs.

Below it can be found the script to obtain effectively clicked slice label and value. Note that also retrieving label and value is slightly different.

var ctx = document.getElementById("chart-area").getContext("2d");
var chart = new Chart(ctx, config);

document.getElementById("chart-area").onclick = function(evt)
{   
    var activePoints = chart.getElementsAtEvent(evt);

    if(activePoints.length > 0)
    {
      //get the internal index of slice in pie chart
      var clickedElementindex = activePoints[0]["_index"];

      //get specific label by index 
      var label = chart.data.labels[clickedElementindex];

      //get value by index      
      var value = chart.data.datasets[0].data[clickedElementindex];

      /* other stuff that requires slice's label and value */
   }
}

Hope it helps.


You can add in the options section an onClick function, like this:

options : {
    cutoutPercentage: 50, //for donuts pie
    onClick: function(event, chartElements){
        if(chartElements){
            console.log(chartElements[0].label);
        }
    },
},

the chartElements[0] is the clicked section of your chart, no need to use getElementsAtEvent anymore. It works on Chart v2.9.4


Examples related to javascript

need to add a class to an element How to make a variable accessible outside a function? Hide Signs that Meteor.js was Used How to create a showdown.js markdown extension Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Summing radio input values How to execute an action before close metro app WinJS javascript, for loop defines a dynamic variable name Getting all files in directory with ajax

Examples related to jquery

How to make a variable accessible outside a function? Jquery assiging class to th in a table Please help me convert this script to a simple image slider Highlight Anchor Links when user manually scrolls? Getting all files in directory with ajax Bootstrap 4 multiselect dropdown Cross-Origin Read Blocking (CORB) bootstrap 4 file input doesn't show the file name Jquery AJAX: No 'Access-Control-Allow-Origin' header is present on the requested resource how to remove json object key and value.?

Examples related to charts

how to set start value as "0" in chartjs? Removing legend on charts with chart.js v2 How to display pie chart data values of each slice in chart.js How to set ChartJS Y axis title? In Chart.js set chart title, name of x axis and y axis? Android charting libraries Click events on Pie Charts in Chart.js Swap x and y axis without manually swapping values How to clear a chart from a canvas so that hover events cannot be triggered? Remove x-axis label/text in chart.js

Examples related to chart.js

Set height of chart in Chart.js how to set start value as "0" in chartjs? Setting width and height Chart.js v2 hide dataset labels How to format x-axis time scale values in Chart.js v2 How to set ChartJS Y axis title? how to display data values on Chart.js How to set max and min value for Y axis JavaScript Chart.js - Custom data formatting to display on tooltip In Chart.js set chart title, name of x axis and y axis?