Google图表:在循环中设置多个监听器会覆盖之前的监听器
Google Charts: setting up multiple listeners in a loop overwrites the previous ones
在一个网页上,我展示了我在 for 循环中创建的多个 Google 图表(用户可以 select 他想查看多少个包含不同数据集的图表)。我是这样做的:
google.charts.load('current', {packages: ['corechart']});
google.charts.setOnLoadCallback(drawTable);
var arrayData = new Array();
var arrayChart = new Array();
function drawTable() {
for (var i = 0; i < {{ length }}; i++) {
var JSONdata = document.getElementById(i);
arrayData['data' + i] = new google.visualization.DataTable(JSONdata.innerHTML);
arrayChart['chart' + i] = new google.visualization.AreaChart(document.getElementById(i));
var options = {};
arrayChart['chart' + i].draw(arrayData['data' + i], options);
}
这按预期工作。 {{ length }}
是一个 Jinja 变量,表示用户想要查看的图表数量,也是包含数据的 <div>
id。
我想为每个图表添加一个侦听器,所以我在第一个循环之外添加了另一个 for 循环:
for (i = 0; i < {{ length }}; i++){
var chart = arrayChart['chart' + i];
var data = arrayData['data' + i];
console.log("Container id: " + chart.container.id);
google.visualization.events.addListener(chart, 'select', function () {
selectHandler(chart, data);
});
}
在上面的部分中,console.log("Container id: " + chart.container.id);
returns Container id: 0, Container id: 1....
用于定义 {{ length }}
.
当用户 select 要查看一张图时({{ length }} = 1
),事件侦听器可以正常工作。
当 {{ length }} > 1
,因此页面上有多个图表时,事件侦听器出现在所有图表上,但只执行循环中最后创建的图表中的内容。
这是select处理函数:
function selectHandler(myChart, myData) {
// I want to do stuff in tables in different <table> with id=trendsTable + number
// myChart.container.id is equal to the number in id=trendsTable + number
console.log("trendsTable"+ myChart.container.id);
var table = document.getElementById("trendsTable" + myChart.container.id);
var tbodyRowCount = table.tBodies[0].rows.length;
var selectedItem = myChart.getSelection()[0];
if (selectedItem) {
var topping = myData.getValue(selectedItem.row, 0);
alert(topping)
}
// Do some more stuff
}
在这种情况下,在 console.log("trendsTable"+ myChart.container.id);
中,myChart.container.id
始终是循环中的最后一个,即使我单击上面的图表(应该有 myChart.container.id - 1
)也是如此。例如,如果有两个图表,如果我点击第一个,我会得到 trendsTable1
而不是 trendsTable0
,如果我点击第二个,我也会得到 trendsTable1
。
我怀疑我在动态声明事件侦听器时做错了什么。有人有什么建议吗?
谢谢
好的,所以我发现是问题所在。并不是我在循环中声明了事件侦听器,而是我传递给 selectHandler
的数据在每次迭代时都被覆盖了。
This post 帮助我理解了 JS 中的闭包,并帮助我修复了用于创建侦听器的循环:
for (i = 0; i < {{ length }}; i++){
(function () {
var chart = arrayChart['chart' + i];
var data = arrayData['data' + i];
// console.log("Container id: " + chart.container.id);
google.visualization.events.addListener(arrayChart['chart' + i], 'select', function () {
selectHandler(chart, data);
}, false);
}());
}
希望这对其他人有帮助
在一个网页上,我展示了我在 for 循环中创建的多个 Google 图表(用户可以 select 他想查看多少个包含不同数据集的图表)。我是这样做的:
google.charts.load('current', {packages: ['corechart']});
google.charts.setOnLoadCallback(drawTable);
var arrayData = new Array();
var arrayChart = new Array();
function drawTable() {
for (var i = 0; i < {{ length }}; i++) {
var JSONdata = document.getElementById(i);
arrayData['data' + i] = new google.visualization.DataTable(JSONdata.innerHTML);
arrayChart['chart' + i] = new google.visualization.AreaChart(document.getElementById(i));
var options = {};
arrayChart['chart' + i].draw(arrayData['data' + i], options);
}
这按预期工作。 {{ length }}
是一个 Jinja 变量,表示用户想要查看的图表数量,也是包含数据的 <div>
id。
我想为每个图表添加一个侦听器,所以我在第一个循环之外添加了另一个 for 循环:
for (i = 0; i < {{ length }}; i++){
var chart = arrayChart['chart' + i];
var data = arrayData['data' + i];
console.log("Container id: " + chart.container.id);
google.visualization.events.addListener(chart, 'select', function () {
selectHandler(chart, data);
});
}
在上面的部分中,console.log("Container id: " + chart.container.id);
returns Container id: 0, Container id: 1....
用于定义 {{ length }}
.
当用户 select 要查看一张图时({{ length }} = 1
),事件侦听器可以正常工作。
当 {{ length }} > 1
,因此页面上有多个图表时,事件侦听器出现在所有图表上,但只执行循环中最后创建的图表中的内容。
这是select处理函数:
function selectHandler(myChart, myData) {
// I want to do stuff in tables in different <table> with id=trendsTable + number
// myChart.container.id is equal to the number in id=trendsTable + number
console.log("trendsTable"+ myChart.container.id);
var table = document.getElementById("trendsTable" + myChart.container.id);
var tbodyRowCount = table.tBodies[0].rows.length;
var selectedItem = myChart.getSelection()[0];
if (selectedItem) {
var topping = myData.getValue(selectedItem.row, 0);
alert(topping)
}
// Do some more stuff
}
在这种情况下,在 console.log("trendsTable"+ myChart.container.id);
中,myChart.container.id
始终是循环中的最后一个,即使我单击上面的图表(应该有 myChart.container.id - 1
)也是如此。例如,如果有两个图表,如果我点击第一个,我会得到 trendsTable1
而不是 trendsTable0
,如果我点击第二个,我也会得到 trendsTable1
。
我怀疑我在动态声明事件侦听器时做错了什么。有人有什么建议吗?
谢谢
好的,所以我发现是问题所在。并不是我在循环中声明了事件侦听器,而是我传递给 selectHandler
的数据在每次迭代时都被覆盖了。
This post 帮助我理解了 JS 中的闭包,并帮助我修复了用于创建侦听器的循环:
for (i = 0; i < {{ length }}; i++){
(function () {
var chart = arrayChart['chart' + i];
var data = arrayData['data' + i];
// console.log("Container id: " + chart.container.id);
google.visualization.events.addListener(arrayChart['chart' + i], 'select', function () {
selectHandler(chart, data);
}, false);
}());
}
希望这对其他人有帮助