Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mouse Click Events in ChartJS 2.X #2292

Closed
ckoeber opened this issue Apr 18, 2016 · 10 comments
Closed

Mouse Click Events in ChartJS 2.X #2292

ckoeber opened this issue Apr 18, 2016 · 10 comments

Comments

@ckoeber
Copy link

ckoeber commented Apr 18, 2016

Hello,

I have been attempting to write mouse click events for a pie chart in ChartJS 2.X but the "getSegmentsAtEvent(evt)" function doesn't seem to be available in the newer version.

Instead, I have getDataelementAtEvenyt(evt), getElementAtEvent(evt), and getElementsAtEvent(evt).

The problem is I am not sure how to use the object returned; it doesn't have any of the previous types of functions/data that the existing object returned used to have.

How do I use the new objects/classes returned?

Thank you for your time.

@etimberg
Copy link
Member

@ckoeber the returned objects will be points / bars / arcs depending on the chart type. If you look in the _model property you will see all of the info about the point. _view will contain all of the properties as they are currently displayed. The values in _view will change during animations

@kissgs
Copy link

kissgs commented Jun 2, 2016

I have a doughnut chart and am trying to use the activePoint = chart.getElementAtEvent(evt) to get the element clicked (in this case the slice). When I do a console.log(activePoint) it shows the same object no matter which slice I click on. I just need to get the information about the slice (label, value) that was clicked. The _view and _model values always return the info about the 1st dataset not the one clicked.

The getDatasetAtEvent returns all the slices objects but that doesn't help since I only care about the one clicked. I know I am probably missing something obvious here.

Any help would be appreciated. Thanks!

@willdady
Copy link

willdady commented Jun 8, 2016

I too am looking to do the same as @kissgs

Also, the ChartElement returned by getElementAtEvent seems to have all it's properties prefixed with an underscore which feels like they're for internal use only. It would be great if ChartElement exposed a formal (documented) API for extracting the underlying data.

@dangre00
Copy link

dangre00 commented Aug 5, 2016

This works for me: FIDDLE INCLUDED

document.getElementById("myChart").onclick = function(evt){
            var activePoints = myChart.getElementsAtEvent(evt);
            var firstPoint = activePoints[0];
            var label = myChart.data.labels[firstPoint._index];
            var value = myChart.data.datasets[firstPoint._datasetIndex].data[firstPoint._index];
            alert(label + ": " + value);
        };

@etimberg etimberg added this to the Version 2.5 milestone Oct 23, 2016
@sloan58
Copy link

sloan58 commented Oct 28, 2016

I'm implementing a click feature as provided by @dangre00 and have run into an issue when the chart is reloaded. It's a Vue.js component that allows filtering the chart data with a select box. The initial page load functions properly and the label and value are logged to the console in my case, but when I refresh the data with AJAX, I get really sporadic behavior. Clicks will return multiple data sets, or undefined. If I click around between bars in the chart they will return different results at random. My Vue component is below. Any suggestions on fixing the click events when the chart is reloaded?

import Chart from 'chart.js';

export default {
template: `
    <div v-bind:class="[chartDivSize]">
        <div class="card">
            <div class="header">
                <div class="row">
                    <div class="col-md-6">
                        <h4 class="title">
                            {{ title }}
                        </h4>
                        <p class="category">{{ category }}</p>
                    </div>
                    <div v-if="isManager" class="col-md-4 pull-right">
                        <h4 class="title pull-right">Filter by Team</h4>
                        <select v-model="selectedFilter" @change="reload" class="form-control selectpicker">
                            <option v-for="filter in filters">{{ filter }}</option>
                        </select>
                    </div>
                </div>
            </div>
                <div class="content">
                    <canvas v-bind:id="chartId" style="height: 352px; width: 704px;" width="1408" height="704"></canvas>
                </div>
                <div class="footer">
                    <div class="legend">
                    </div>
                    <hr>
                    <div class="stats">
                        <i class="fa fa-clock-o"></i>{{ stats }}
                    </div>
                </div>
            </div>
        </div>
    </div>
`,

props: ['ctx', 'chart', 'url', 'chartId', 'chartDivSize', 'title', 'category', 'stats', 'filters', 'isManager', 'selectedFilter', 'activePoints'],

ready() {
    this.load();
},

methods: {
    load() {
        this.fetchData().then(
            response => this.render(response.data)
        );
    },
    fetchData() {
        if(this.selectedFilter) {
            var resource = this.$resource(this.url);
            return resource.get({ filter: this.selectedFilter });
        } else {
            return this.$http.get(this.url);
        }
    },
    render(data) {
        this.title = data.title;
        this.category = data.category;
        this.stats = data.stats;
        this.filters = data.filters;
        this.filters.unshift('All');
        if(data.selectedFilter) {
            this.selectedFilter = data.selectedFilter;
        } else {
            this.selectedFilter = 'All';
        }
        this.isManager = data.isManager;

        this.ctx = $("#" + this.chartId);

        var chartData = {
            labels: data.labels,
            datasets: [
                {
                    label: data.metric,
                    data: data.data,
                    backgroundColor: data.background_colors,
                    hoverBackgroundColor: data.hover_colors
                }]
        };

        this.chart = new Chart(this.ctx, {
            type: "bar",
            data: chartData,
            options: {
                scaleLabel: {
                    display: true
                },
                scales: {
                    yAxes: [{
                        ticks: {
                            beginAtZero: true,
                            fontStyle: "bold"
                        }
                    }],
                    xAxes: [{
                        ticks: {
                            beginAtZero: true,
                            fontStyle: "bold"
                        }
                    }]
                },
                legend: {
                    display: false
                }
            }
        });

        this.$nextTick(() => {
            this.setChartClickHandler(this.ctx, this.chart);
        });

    },
    reload() {
        this.chart.destroy();
        this.load();
    },

    setChartClickHandler(ctx, chart) {
        ctx.on('click', evt => {
            var activePoints = chart.getElementsAtEvent(evt);
            var label = chart.data.labels[activePoints[0]._index];
            var value = chart.data.datasets[activePoints[0]._datasetIndex].data[activePoints[0]._index];
            console.log(label,value);
        });
    },
},

}`

@jVerz
Copy link

jVerz commented Nov 22, 2016

when using multiple datasets in a bar chart
_datasetIndex always seems to be 0?
when data set "0" is hidden it wil return 1

@etimberg etimberg modified the milestones: Version 2.6, Version 2.5 Jan 20, 2017
@etimberg etimberg modified the milestones: Version 2.7, Version 2.6 Apr 16, 2017
@thirossato
Copy link

thirossato commented Jun 14, 2017

How do i get the clicked point instead of first?
For example i have a mixed chart, with bar and line charts, so i have like 4 datasets, i want to add a click listener that return the selected point.

Edit:
Nevermind, i found myself a solution, follow for anyone with same doubt:

document.getElementById("myChart").onclick = function (evt) {
        var activePoints = myChart.getElementsAtEventForMode(evt, 'point', myChart.options);
        var firstPoint = activePoints[0];
        var label = myChart.data.labels[firstPoint._index];
        var value = myChart.data.datasets[firstPoint._datasetIndex].data[firstPoint._index];
        alert(label + ": " + value);
    };

@dnyanesh7585
Copy link

dnyanesh7585 commented Feb 5, 2018

Here is a solution,
`

$scope.onClick = function (points, evt) {
var Check = angular.fromJson(points[0]._model);
alert(Check);
}`

@brich2018
Copy link

Lil rough but this worked for me:
let queueName = e.active[0]._chart.tooltip._model.body[0].lines[0];
queueName = queueName.substring(0, queueName.indexOf(':'));

@reya276
Copy link

reya276 commented Aug 9, 2019

How can I use the onclick event for a chart with multiple series?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
No open projects
Development

No branches or pull requests