我正在开发一个 R Shiny 应用程序,构建一个图表列表,我希望通过单击每个图表下方的按钮来下载每个数据。
我的问题是,为处理
downloadHandler
内容参数而创建的匿名函数仅在单击我的按钮时才会被解释,并且我无法检索用户按下哪个按钮来分派正确的数据下载。
plot_ids是plot_id的列表
["plot_1","plot_2",...]
plot_data 是一个命名的数据列表
["plot_1"=tibble(),"plot_2"=tibble(),...]
for (plot_id in plot_ids) {
output[[plot_id]] <- downloadHandler(
filename = function() {
paste0("custom_export_", plot_id, ".csv")
},
content = function(file){
write.csv(plot_data[[plot_id]], file, row.names = FALSE)
}
)
}
如果我生成多个绘图,则所有 downloadButton 和 downloadLink 都会链接到最后生成的绘图,因为
function(file){...}
在用户单击时被解释,然后plot_id 设置为 for 循环设置的最后一个值。
我还尝试使用
as.function()
生成匿名函数,以设置默认参数 function(file,local_plot_id=plot_id)
,或使用包装函数。
我终于使用
local
函数找到了问题的答案
在本地环境中计算表达式。它相当于local
,只不过它的默认参数创建了一个新的空环境。这对于创建匿名递归函数非常有用,并且作为一种有限的命名空间功能,因为环境中定义的变量从外部不可见。evalq
这是我的问题中本地使用的示例代码
for (plot_id in plot_ids) {
output[[plot_id]] <- local({
local_plot_id <- plot_id
downloadHandler(
filename = function() {
paste0("custom_export_", local_plot_id, ".csv")
},
content = function(file){
write.csv(plot_data[[local_plot_id]], file, row.names = FALSE)
}
)
})
}