Click events on Pie Charts in Chart.js

JavascriptJqueryChartschart.js

Javascript Problem Overview


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?

Javascript Solutions


Solution 1 - Javascript

Update: As @Soham Shetty comments, getSegmentsAtEvent(event) only works for 1.x and for 2.x getElementsAtEvent should be used.

> .getElementsAtEvent(e) > > Looks for the element under the event point, then returns all elements > at the same data index. This is used internally for 'label' mode > highlighting. > > Calling getElementsAtEvent(event) on your Chart instance passing an > argument of an event, or jQuery event, will return the point elements > that are at that the same position of that event. > > canvas.onclick = function(evt){ > var activePoints = myLineChart.getElementsAtEvent(evt); > // => activePoints is an array of points on the canvas that are at the same position as the click event. > };

Example: https://jsfiddle.net/u1szh96g/208/


Original answer (valid for Chart.js 1.x version):

You can achieve this using getSegmentsAtEvent(event)

> Calling getSegmentsAtEvent(event) on your Chart instance passing an > argument of an event, or jQuery event, will return the segment > elements that are at that the same position of that event.

From: Prototype Methods

So you can do:

$("#myChart").click( 
	function(evt){
		var activePoints = myNewChart.getSegmentsAtEvent(evt);           
        /* do something */
	}
);	

			

Here is a full working example:

<html>
	<head>
		<script type="text/javascript" src="http://code.jquery.com/jquery-2.0.2.js"></script>
		<script type="text/javascript" src="Chart.js"></script>
		<script type="text/javascript">
			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"
				}
			];
			
			$(document).ready( 
				function () {
					var ctx = document.getElementById("myChart").getContext("2d");
					var myNewChart = new Chart(ctx).Pie(data);
					
					$("#myChart").click( 
						function(evt){
							var activePoints = myNewChart.getSegmentsAtEvent(evt);
							var url = "http://example.com/?label=" + activePoints[0].label + "&value=" + activePoints[0].value;
							alert(url);
						}
					);					
				}
			);
		</script>
	</head>
	<body>
		<canvas id="myChart" width="400" height="400"></canvas>
	</body>
</html>

Solution 2 - Javascript

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][1].

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. [1]: http://www.chartjs.org/docs/#advanced-usage-prototype-methods

Solution 3 - Javascript

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.

Solution 4 - Javascript

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);
                    }
                }

Solution 5 - Javascript

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>

Solution 6 - Javascript

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 ... */
	}
};

Solution 7 - Javascript

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);
    }



}

Solution 8 - Javascript

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>

Solution 9 - Javascript

  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;
                
                      });

Solution 10 - Javascript

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

Solution 11 - Javascript

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);
    }
    
  }
}

Solution 12 - Javascript

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]); 


} 
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionNewttView Question on Stackoverflow
Solution 1 - JavascriptTobíasView Answer on Stackoverflow
Solution 2 - JavascriptalessandrobView Answer on Stackoverflow
Solution 3 - JavascriptTom GloverView Answer on Stackoverflow
Solution 4 - JavascriptLakshmi RMView Answer on Stackoverflow
Solution 5 - JavascriptSachin RaghavView Answer on Stackoverflow
Solution 6 - JavascriptAnwarView Answer on Stackoverflow
Solution 7 - JavascriptSteve The SultanView Answer on Stackoverflow
Solution 8 - JavascriptCarlo BosView Answer on Stackoverflow
Solution 9 - JavascriptPradipPatel1411View Answer on Stackoverflow
Solution 10 - JavascriptDavid AndriantsilavoView Answer on Stackoverflow
Solution 11 - JavascriptprashantView Answer on Stackoverflow
Solution 12 - Javascriptjared maldonadoView Answer on Stackoverflow