Google Charts调用setColumns切换列后丢失最后一行数据问题
看起来你的问题核心是:当切换列的显示状态后,最后一行数据消失了,但原始数据明明还存在。我来帮你分析下可能的原因和修复方案:
可能的根源
Google Charts的DataView有一个默认行为:如果某一行在所有可见列中的值都是空的,它会自动过滤掉这一行。看你提供的最后一行数据:
0:{wf: "10 May 2018, 14:44:36"} 1:{wf: ""} 2:{wf: ""} ... 7:{wf: ""} 8:{wf: "69.9"} ... 14:{wf: "28.6"}
这一行只有第0列和8-14列有值,1-7列全是空。所以当你切换列后,如果可见列中不包含0列,也不包含8-14列(比如只显示1-7列),这一行就会被DataView判定为全空而过滤掉,导致行数从45变成44。
另外,还有一种可能是你的_dashboard绑定的控件(比如过滤器)不小心排除了最后一行,比如日期过滤器的范围没包含最后一行的时间。
修复步骤
1. 先确认问题出在DataView还是控件
在你的performColumnToggle函数里,设置完_view.setColumns(_toggledColumns);之后,添加一行日志:
console.log("DataView行数:", _view.getNumberOfRows());
- 如果输出是45:说明
DataView本身是完整的,问题出在_dashboard的控件上。你需要检查控件的配置,比如日期过滤器是否自动计算的范围漏掉了最后一行,或者控件的过滤规则排除了它。 - 如果输出是44:说明
DataView确实过滤了最后一行,那就是可见列的问题,继续看下面的修复。
2. 确保关键列始终可见
既然最后一行的第0列有值,你可以把第0列设为不可隐藏,或者在切换列时强制它始终在可见列表中。修改你的performColumnToggle函数:
performColumnToggle: function (col) { // 禁止切换第0列(保证最后一行始终有可见的非空值) if (col === 0) return; _view = new google.visualization.DataView(_original_data); var key = $.inArray(col, _toggledColumns); if (_columns[col]['status'] === 1) { _columns[col]['status'] = 0; if (key !== -1) { _toggledColumns.splice(key, 1); } } else { _columns[col]['status'] = 1; // 保持列的顺序,插入到正确位置 var insertIndex = _toggledColumns.findIndex(c => c > col); if (insertIndex === -1) { _toggledColumns.push(col); } else { _toggledColumns.splice(insertIndex, 0, col); } } // 强制第0列始终在可见列表中 if ($.inArray(0, _toggledColumns) === -1) { _toggledColumns.unshift(0); _columns[0]['status'] = 1; } _view.setColumns(_toggledColumns); console.log("DataView行数:", _view.getNumberOfRows()); // 现在应该是45了 _dashboard.draw(_view); }
3. 检查列切换逻辑的正确性
你原来的代码中,使用_toggledColumns.splice(col, 0, col)插入列,这可能会导致列顺序混乱,甚至插入错误的位置(比如当_toggledColumns不是连续的列索引时)。上面的代码改用findIndex来找到正确的插入位置,保证列顺序和原始数据一致。
4. 验证原始数据的完整性
虽然你说console.log(_original_data)能看到45行,但还是建议你在每次更新数据后,打印_original_data.getNumberOfRows()确认,避免因为引用传递导致_original_data被意外修改:
updateData: function () { _tableData = data; _data = new google.visualization.DataTable(_tableData); _original_data = _data; console.log("原始数据行数:", _original_data.getNumberOfRows()); // 确认是45 // 其他代码... }
额外提示
如果你的Select/Diselect All按钮是用来切换所有列的显示,记得要排除第0列,或者在切换后强制把第0列加回可见列表,这样就不会出现最后一行被过滤的情况了。
内容的提问来源于stack exchange,提问作者Vlad Vladimir Hercules

