Reputation: 1515
I'm trying to create an arbitrary number of Google visualization charts with different data sources. Since there are an arbitrary number, I'm looping through elements by class name, querying the data for each, and then drawing the chart in the query.send callback. That callback doesn't take any parameters, so I have no way to pass in the element for which the chart should be drawn. So, I tried doing it with global variables; however, the loop iterates, overwriting the variables before the query returns. What's the right way to do this?
let cwraggbgraphs = [];
let cwraggbgraph = "";
google.charts.load('current', {'packages':['corechart']});
google.charts.setOnLoadCallback(initializeData);
function initializeData() {
cwraggbgraphs = document.getElementsByClassName("cwraggbp");
// loop through each of the divs by class name
for (var i = 0; i < cwraggbgraphs.length; i++) {
// set the global variable to the element we need to target
cwraggbgraph = cwraggbgraphs.item(i);
var opts = {sendMethod: 'auto',
csvColumns: ['string', 'number', 'number'],
csvHasHeader: true};
// the URL from which to grab the data is set in a data attribute on the element
var query = new google.visualization.Query(
cwraggbgraph.dataset.cwraggbpSrc,
opts);
query.send(handleQueryResponse);
}
}
// when we get a response, draw the chart
function handleQueryResponse(response) {
console.log("Got response ", response);
// this works, I get all of the responses back
console.log("Using element ", cwraggbgraph);
// but by the time the 1st response returns, the for loop has completed,
// so this is always the last element :(
if (response.isError()) {
alert('Error in query: '
+ response.getMessage()
+ ' '
+ response.getDetailedMessage());
return;
}
let data = response.getDataTable();
let chart = new google.visualization.PieChart(cwraggbgraph);
chart.draw(data, {width: 400, height: 240, is3D: true});
}
Initially, I tried to do this by passing the element to the callback, but it only takes a single parameter. That's what got me to trying to do it with global variables, but then I ran into this timing issue. Any ideas on how to accomplish this?
Upvotes: 1
Views: 60
Reputation: 61222
you can use an "in between", anonymous function...
query.send(function (response) {
handleQueryResponse(response, cwraggbgraph);
});
see following snippet...
google.charts.setOnLoadCallback(initializeData);
function initializeData() {
var cwraggbgraphs = document.getElementsByClassName("cwraggbp");
// loop through each of the divs by class name
for (var i = 0; i < cwraggbgraphs.length; i++) {
// set the global variable to the element we need to target
var cwraggbgraph = cwraggbgraphs.item(i);
var opts = {sendMethod: 'auto',
csvColumns: ['string', 'number', 'number'],
csvHasHeader: true};
// the URL from which to grab the data is set in a data attribute on the element
var query = new google.visualization.Query(
cwraggbgraph.dataset.cwraggbpSrc,
opts);
query.send(function (response) {
handleQueryResponse(response, cwraggbgraph);
});
}
}
// when we get a response, draw the chart
function handleQueryResponse(response, cwraggbgraph) {
if (response.isError()) {
alert('Error in query: '
+ response.getMessage()
+ ' '
+ response.getDetailedMessage());
return;
}
let data = response.getDataTable();
let chart = new google.visualization.PieChart(cwraggbgraph);
chart.draw(data, {width: 400, height: 240, is3D: true});
}
Upvotes: 1