I'm trying to display the total value of a barchart where 'isStacked: true' on a <span>
located on top of the chart when I click on a bar.
My reference to explore the capability of google.visualization.events.addListener started here.
When I click the a bar I recieved this error:
Uncaught TypeError: Cannot read property 'row' of undefined
or when I change the row
to column
Uncaught TypeError: Cannot read property 'column' of undefined
Any pointers is really appreciated.
Here's my django template:
<script type="text/javascript">
$(document).ready(function(){
{% for staff_name, staff_id in params.items %}
$.ajax({
url: "{% url user_kpi %}",
data: { user_stat: {{staff_name}} },
success: function(responseData) {
if (typeof responseData=="object") {
var data = new google.visualization.arrayToDataTable([
['Type', 'Processed Items', { role: 'style' }, 'Processed beyond Due Date', { role: 'style'}],
['PPP', responseData['PPP_ontime'], 'lightgreen', responseData['PPP_due'], 'red'],
['CP', responseData['CP_ontime'], 'gold', responseData['CP_due'], 'red'],
['RSL', responseData['RSL_ontime'], 'lightblue', responseData['RSL_due'], 'red'],
['MOD', responseData['MOD_ontime'], 'yellow', responseData['MOD_due'], 'red' ],
['STO', responseData['RECALL_ontime'], 'silver', responseData['RECALL_due'], 'red'],
['TP', responseData['TP_ontime'], 'orange', responseData['TP_due'], 'red'],
['DEMO', responseData['DEMO_ontime'], 'violet', responseData['DEMO_due'], 'red'],
['DUP', responseData['DUP_ontime'], 'brown', responseData['DUP_due'], 'red']]);
google.setOnLoadCallback(drawVisualization(data, {{staff_name}}));
}
}
});
{% endfor %}
});
var wrapper;
function drawVisualization(xdata, id) {
// Create and draw the visualization.
var visual = 'visualization-'+id.toString();
//chart = new google.visualization.BarChart(document.getElementById(visual));
wrapper = new google.visualization.ChartWrapper({
chartType: 'BarChart',
dataTable: xdata,
options: {
width:600, height:140,
vAxis: {title: null, maxValue: 3500},
hAxis: {title: null},
animation: {easing: 'in'},
axisTitlesPosition: "out",
chartArea:{left:0,top:0, right:0, width:"100%",height:"100%"},
focusTarget: "category",
fontSize: 12,
fontName: "Tahoma",
legend: {position: 'none'},
series: [{color: 'black', visibleInLegend: false}, {}, {},
{color: 'red', visibleInLegend: false}],
isStacked: true,
backgroundColor: '#eee',
},
containerId: visual
});
google.visualization.events.addListener(wrapper, 'ready', function() {
// grab a few details before redirecting
google.visualization.events.addListener(wrapper.getChart(), 'select', function() {
chartObject = wrapper.getChart();
// checking value upon mousehover
alert(xdata.getValue(chartObject.getSelection()[0].row, 0));
//alert(xdata.getValue(chartObject.getSelection()[0].column, 0));
});
});
wrapper.draw();
}
Update: As explain by asgallant.
<script type="text/javascript">
function init () {
{% for staff_name, staff_id in params.items %}
$.ajax({
url: "{% url user_kpi %}",
data: { user_stat: {{staff_name}} },
success: function(responseData) {
if (typeof responseData=="object") {
var data = new google.visualization.arrayToDataTable([
['Type', 'Processed Items', { role: 'style' }, 'Processed beyond Due Date', { role: 'style'}],
['PPP', responseData['PPP_ontime'], 'lightgreen', responseData['PPP_due'], 'red'],
['CP', responseData['CP_ontime'], 'gold', responseData['CP_due'], 'red'],
['RSL', responseData['RSL_ontime'], 'lightblue', responseData['RSL_due'], 'red'],
['MOD', responseData['MOD_ontime'], 'yellow', responseData['MOD_due'], 'red' ],
['STO', responseData['RECALL_ontime'], 'silver', responseData['RECALL_due'], 'red'],
['TP', responseData['TP_ontime'], 'orange', responseData['TP_due'], 'red'],
['DEMO', responseData['DEMO_ontime'], 'violet', responseData['DEMO_due'], 'red'],
['DUP', responseData['DUP_ontime'], 'brown', responseData['DUP_due'], 'red']
]);
drawVisualization(data, {{staff_name}});
}
}
});
{% endfor %}
}
google.load('visualization', '1', {packages:['corechart'], callback: init});
function drawVisualization(xdata, id) {
// Create and draw the visualization.
var visual = 'visualization-'+id.toString(),
//chart = new google.visualization.BarChart(document.getElementById(visual));
wrapper = new google.visualization.ChartWrapper({
chartType: 'BarChart',
dataTable: xdata,
options: {
width:600, height:140,
vAxis: {title: null, maxValue: 3500},
hAxis: {title: null},
animation: {easing: 'in'},
axisTitlesPosition: "out",
chartArea:{left:0,top:0, right:0, width:"100%",height:"100%"},
focusTarget: "category",
fontSize: 12,
fontName: "Tahoma",
legend: {position: 'none'},
//orientation: "vertical"
series: [{color: 'black', visibleInLegend: false}, {}, {},
{color: 'red', visibleInLegend: false}],
isStacked: true,
backgroundColor: '#eee',
},
containerId: visual
});
google.visualization.events.addListener(wrapper, 'ready', function() {
var chart = wrapper.getChart();
google.visualization.events.addListener(chart, 'select', function() {
var selection = chart.getSelection();
if (selection.length) {
// the user selected a bar
alert(xdata.getValue(selection[0].row, 0));
//alert(selection.length);
}
else {
alert('no selection');// the user deselected a bar
}
});
});
wrapper.draw();
}
Error: Uncaught Error: Invalid row index undefined. Should be in the range [0-7].
Corrrected by asgallant
Turning this line alert(xdata.getValue(selection.row, 0));
into alert(xdata.getValue(selection[0].row, 0));
First, you AJAX calls should be made inside a callback from the google loader, not from a document ready handler (this guarantees that the the Visualization API is available when you try to use API components):
function init () {
{% for staff_name, staff_id in params.items %}
$.ajax({
url: "{% url user_kpi %}",
data: { user_stat: {{staff_name}} },
success: function(responseData) {
if (typeof responseData=="object") {
var data = new google.visualization.arrayToDataTable([
['Type', 'Processed Items', { role: 'style' }, 'Processed beyond Due Date', { role: 'style'}],
['PPP', responseData['PPP_ontime'], 'lightgreen', responseData['PPP_due'], 'red'],
['CP', responseData['CP_ontime'], 'gold', responseData['CP_due'], 'red'],
['RSL', responseData['RSL_ontime'], 'lightblue', responseData['RSL_due'], 'red'],
['MOD', responseData['MOD_ontime'], 'yellow', responseData['MOD_due'], 'red' ],
['STO', responseData['RECALL_ontime'], 'silver', responseData['RECALL_due'], 'red'],
['TP', responseData['TP_ontime'], 'orange', responseData['TP_due'], 'red'],
['DEMO', responseData['DEMO_ontime'], 'violet', responseData['DEMO_due'], 'red'],
['DUP', responseData['DUP_ontime'], 'brown', responseData['DUP_due'], 'red']
]);
drawVisualization(data, {{staff_name}});
}
}
});
{% endfor %}
}
google.load('visualization', '1', {packages:['corechart'], callback: init});
Then, in your drawVisualization
function, you have a couple of problems: to start with, wrapper
is a global object, so it gets overwritten every time you call drawVisualization
; this is the primary cause of your issue, as the "select" event fires for one chart, but wrapper
refers to the last chart drawn, not the chart clicked on (and thus, the wrapper.getChart().getSelection()
call returns an empty array, element 0 of an empty array is undefined
, and undefined
does not have a row or column property). You need to make wrapper local to the drawVisualization
function instead of global. Delete this line:
var wrapper;
and add var
to the beginning of this line:
wrapper = new google.visualization.ChartWrapper({
Then you need to adjust the event handler to test for the length of the selection array, as the user can click a bar twice, which selects and then deselects the bar, resulting in an empty array, and you would get the same error. The event handler needs to look like this:
google.visualization.events.addListener(wrapper, 'ready', function() {
var chart = wrapper.getChart();
google.visualization.events.addListener(chart, 'select', function() {
var selection = chart.getSelection();
if (selection.length) {
// the user selected a bar
alert(xdata.getValue(selection[0].row, 0));
}
else {
// the user deselected a bar
}
});
});
来源:https://stackoverflow.com/questions/20963158/google-visualization-click-event-on-barchart-isstacked-true