Can I put multiple download links in same table cell in shiny?

Viewed 129

I'm using shiny and I'm having trouble inserting multiple links in the same table cell. Every link should allow the user to download local files found on the computer. Here is an image of what I mean: table with links

For columns 2, 3, and 4, whose rows include at most only 1 link, it works perfectly; when I click on the hyperlinks I am able to download the corresponding file from my pc. However, for column 5, which includes multiple hyperlinks in each cell, I am unable to do so. Clicking on the links returns nothing; no file is downloaded (but I don't get an error).

This is the code I'm using for column 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)

In case something is missing or you need further clarification, I asked this question in more detail (with my code) on the rstudio forum (haven't received an answer though): https://community.rstudio.com/t/multiple-links-in-same-table-cell/110558

Thank you in advance.

1 Answers

I think this should do it by replacing the for loop with lapply in the renderUI part and generating the downloadLink as a 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")
      )
    })
      }
  })
})

and putting the downloadHandler outputs in a local environment to generate unique IDs with the for loop:

  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)
      }

    )
    })
    }}
})

I had to replace your panels=panels$"Gene panel" line with panels=panels[[1]] to make it work with my test dataframe, I was able to "display" the 6 hidden links of your example data.

Related