【问题标题】:Can I put multiple download links in same table cell in shiny?我可以在闪亮的同一个表格单元格中放置多个下载链接吗?
【发布时间】:2021-08-07 16:22:39
【问题描述】:

我正在使用 Shiny,但无法在同一个表格单元格中插入多个链接。每个链接都应允许用户下载在计算机上找到的本地文件。 这是我的意思的图像: table with links

对于第 2、3 和 4 列,其行最多只包含 1 个链接,它可以正常工作;当我点击超链接时,我可以从我的电脑下载相应的文件。但是,对于在每个单元格中包含多个超链接的第 5 列,我无法这样做。单击链接不会返回任何内容;没有下载文件(但我没有收到错误消息)。

这是我用于第 5 列的代码:

lapply(1:nrow(table), function(i) {
 if (table[i,5]!="No panels")
    {
      panels=strsplit(table[i,5], "<br>")
      panels=panels$`Gene panel`
      for (j in 1:length(panels)){
      output[[paste0("downloadData", i, j, 4)]] <- downloadHandler( # as opposed to before, I added here another variable 'j' in the name of the output variable to differentiate between the different panels for each sample name
        filename=paste("./Gene_panel/", table[i,1], "_", panels[j], sep=""),  
        content = function(file) {
          file.copy(paste("./Gene_panel/", table[i,1], "_", panels[j], sep=""), file)
        }
      )}}
    }
  )

output$hidden_downloads_panel <- renderUI(
    lapply(1:nrow(table), function(i) {
      if (table[i,5]!="No panels"){
      panels=strsplit(table[i,5], "<br>")
      panels=panels$`Gene panel`
      for (j in 1:length(panels)){
      downloadLink(paste0("downloadData", i, j, 4), "download", class = "hiddenLink") # also added 'j' here
      }
      }
    }))

  output$table <- renderDataTable({ # here, it's the same as before but I just added the last '%>% mutate' to accommodate the last column 'Gene panel'
    table=as.data.frame(table)%>%
      mutate("Quality Control" = lapply(1:n(),
                           function(i)
                           { if (table[i,2]=="Yes"){
                             paste0('<a href="#" onClick=document.getElementById("downloadData',i, 1,'").click() >Yes</a>')}
                             else 
                               paste0("No")}
      ))%>% mutate("BWA" = lapply(1:n(),
                                  function(i)
                                  { if (table[i,3]=="Yes"){
                                    paste0('<a href="#" onClick=document.getElementById("downloadData',i,2, '").click() >Yes</a>')}
                                    else 
                                      paste0("No")}))%>% mutate("Annotation" = lapply(1:n(),
                              function(i)
                              { if (table[i,4]=="Yes"){
                                paste0('<a href="#" onClick=document.getElementById("downloadData',i,3, '").click() >Yes</a>')}
                                else 
                                  paste0("No")}))%>% mutate("Gene panel" = lapply(1:n(),
                                     function(i)
     if (table[i,5]!="No panels"){
        panels=strsplit(table[i,5], "<br>")   
        panels=panels$`Gene panel`
        list=c()
        for (j in 1:length(panels))
        {
        list=append(list,paste0('<a href="#" onClick=document.getElementById("downloadData', i, j, 4, '").click() >', panels[j], '</a>')) 
        }
        paste0(list, collapse="<br>")
      }
    else
      paste0("No panels")                 
))
    table
  }, escape = F)

如果缺少某些内容或您需要进一步澄清,我在 rstudio 论坛上(使用我的代码)更详细地提出了这个问题(虽然还没有收到答案):https://community.rstudio.com/t/multiple-links-in-same-table-cell/110558

提前谢谢你。

【问题讨论】:

  • 当您说“我无法这样做”或“它不起作用”(在您的其他帖子中)时,错误的行为或错误信息是什么?请在此处同时提供您的应用代码。
  • 感谢您的回复。通过“它不起作用”,我的意思是当我点击超链接时没有任何反应。没有错误,但没有下载任何内容。没问题,我这里也加了代码。
  • 如果没有使用完整代码和一些示例数据来测试应用程序的可能性,这是很困难的。这可能与 for 循环没有为每个链接 (see this) 生成唯一 ID 并需要使用 local() 有关,但我想您至少会获得一个下载链接。您可以在浏览器中检查每个 downloadLink 生成的 ID(Firefox 或 Chrome 上的 F12)吗?
  • 我实际上很确定每个链接都有其唯一的 ID,但我不知道如何使用 F12 获取它(我试过但找不到任何链接)。但是,我确实尝试在每个for (j in 1:length(panels)) 上使用print(i, j, panels[j]),并且我在相应的基因面板上都得到了相同的数字 3 次。例如,我在每个循环中得到“11EPILEPSY GENE PANEL.csv”,然后是“12INTELLECTUAL DISABILITY GENE PANEL.csv:, 等等。希望这会有所帮助。如果使用 F12 会让我们确定循环正在生成唯一 ID,请告诉我在哪里可以找到链接?感谢您的耐心等待。
  • 打开浏览器的开发者工具,通常使用F12,或在工具菜单中,或右键单击您的应用并选择“检查”。然后可以访问Shiny生成的HTML源代码(Firefox InspectorChrome Elements),尝试找到每个链接ID。使用左上角的选择器图标(节点选择器),您只需将鼠标悬停在页面中的相应元素上即可选择正确的代码。

标签: r shiny


【解决方案1】:

我认为这应该通过用renderUI 部分中的lapply 替换for 循环并将downloadLink 生成为tagList 来实现:

  output$hidden_downloads_panel <- renderUI({
outputlist <- lapply(1:nrow(table), function(i) {
  if (table[i,5]!="No panels"){
    panels=strsplit(table[i,5], "<br>")
    panels=panels[[1]]
    lapply(1:length(panels), function(j){
      tagList(
      downloadLink(paste0("downloadData", i, j, 4), "download", class = "hiddenLink")
      )
    })
      }
  })
})

并将downloadHandler 输出放在本地环境中,以使用 for 循环生成唯一 ID:

  lapply(1:nrow(table), function(i) {
if (table[i,5]!="No panels")
{
  panels=strsplit(table[i,5], "<br>")
  panels=panels[[1]]
  for (j in 1:length(panels)){
    local({
      my_j = j
    output[[paste0("downloadData", i, my_j, 4)]] <- downloadHandler( 
      filename=paste("./Gene_panel/", table[i,1], "_", panels[my_j], sep=""),  
      content = function(file) {
        file.copy(paste("./Gene_panel/", table[i,1], "_", panels[my_j], sep=""), file)
      }

    )
    })
    }}
})

我不得不用 panels=panels[[1]] 替换您的 panels=panels$"Gene panel" 行,以使其适用于我的测试数据框,我能够“显示”您的示例数据的 6 个隐藏链接。

【讨论】:

  • (我知道 stackoverflow 不喜欢这些类型的 cmets 但是)我快哭了。我已经尝试解决这个问题好几个星期了,它确实奏效了。明天我有一个关于我的 Shiny 界面的会议,并且对这个问题感到压力很大。你是英雄。非常感谢。
  • 很高兴听到!祝您会议顺利
猜你喜欢
  • 1970-01-01
  • 2020-02-23
  • 2020-10-16
  • 2020-07-04
  • 1970-01-01
  • 2010-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多