marimaf
marimaf

Reputation: 5410

Select google chart from list when user clicks on bar

I have a loop that goes through data and creates several google charts. I have added a selectHandler that does something when a bar of a chart is clicked. I have no problem getting the bar selected once I have the chart, but I do not know how to tell the handler which chart was clicked.

Here is the code:

inside the drawChart() which is in a loop:

chart[chart_index] = new google.visualization.BarChart(document.getElementById('chart_div<%= qcount  %>'));
chart[chart_index].draw(data, {width: 450, height: 300, title: 'title'});

google.visualization.events.addListener(chart[chart_index], 'select', selectHandler);
chart_index = chart_index+1;

and the selectHandler works like this:

function selectHandler(e) {
    var bar_index = chart[HERE_GOES_THE_CHART_INDEX].getSelection()[0].row;
}

Thanks

Upvotes: 2

Views: 2497

Answers (3)

ennovum
ennovum

Reputation: 1

Function binding to the rescue.

google.visualization.events.addListener(chart[chart_index], 'select', selectHandler.bind(chart[chart_index]));

Your handler will receive the chart always as the first argument.

If you're targeting older browsers, here's a great binding polyfill by Mozilla crew: MDN Function.prototype.bind()

Upvotes: 0

asgallant
asgallant

Reputation: 26340

There's no way to get the specific chart from the event handler, so you have to use another method of passing the chart to the handler. Here's one way you can do it:

function selectHandler(myChart) {
    // test to see if anything was selected before you get the index
    // otherwise you will get errors when the selection contains 0 elements
    var selection = myChart.getSelection();
    if (selection.length) {
        var bar_index = selection[0].row;
        // do something with bar_index
        // you should also test bar_index, as the user could have clicked a legend item, which would give a null value for row
    }
}

chart[chart_index] = new google.visualization.BarChart(document.getElementById('chart_div<%= qcount  %>'));
// generally speaking, you should add event handlers before drawing the chart
google.visualization.events.addListener(chart[chart_index], 'select', (function (x) {
    return function () {
        selectHandler(chart[x]);
    }
})(chart_index));
chart[chart_index].draw(data, {width: 450, height: 300, title: 'title'});

chart_index = chart_index+1;

This closure passes chart_index to the inside of the closure, and assigns it to x:

(function (x) {
    return function () {
        selectHandler(chart[x]);
    }
})(chart_index)

so the value of x is locked inside the closure, even when you increment chart_index later. The closure returns a function which becomes the event handler. This function calls selectHandler, passing in chart[x] when someone clicks on a chart element. If you are iterating over this in a loop, the value of x will be unique inside each closure, giving you the ability to reference specific charts in your selectHandler function.

Upvotes: 4

carter
carter

Reputation: 5442

After reading google visualization event handling...

SELECT Event:

The select event does not pass any properties or objects to the handler (your function handler should not expect any parameters to be passed to it).

So although you can use getSelection(), you need another function to determine which chart is has been acted upon. Enters another event handler:

// google.visualization.table exposes a 'page' event.
google.visualization.events.addListener(table, 'page', myPageEventHandler);
...
function myPageEventHandler(e) {
  alert('The user is navigating to page ' + e['page']);
}

You need an event handler that has event object passed in param so you can determine which chart is being evented. Once you have the current chart, you can use getSelection() to see the current selection in that chart.

Upvotes: 0

Related Questions