Search code examples
rshinytabpanel

downloadHandler fails to execute in other panels of tabPanel


The purpose of my shiny app is for users to import an excel file, and the app will show the table (after some data manipulation). Users also can download and save the table as whatever the name they give.

The code works perfectly fine. However, when I decided to add another tabPanel, the download button works fine in the first panel, but only downloads the HTML in the second Panel rather than the table imported. If it is not clear, you can copy the code ad try and run it. The second panel only download the HTML of the page.

Why does it download the HTML in the second panel, but the same code works perfectly fine in the first panel?

UI:

ui <- fluidPage(
  tabsetPanel(
    tabPanel("Panel1",
             sidebarLayout(
               sidebarPanel(fileInput("df1", "Import File", accept = ".xlsx"),
                            textInput('df1sheet', 'Sheet Name (Case-Sensitive)'),
                            actionButton("update", "Update")),
               mainPanel(tableOutput("table1"), 
                         useShinyjs(),
                         actionButton("download", "Download Table"),
                         conditionalPanel(
                           "false", 
                           downloadButton("downloadtable")
                         ),
                         useShinyalert())
             )),
    tabPanel("Panel2",
             sidebarLayout(
               sidebarPanel(fileInput("df2", "Import File", accept = ".xlsx"),
                            textInput('df2sheet', 'Sheet Name (Case-Sensitive)'),
                            actionButton("update2", "Update")),
               mainPanel(tableOutput("table2"), 
                         useShinyjs(),
                         actionButton("download2", "Download Table"),
                         conditionalPanel(
                           "false", 
                           downloadButton("downloadtable2")
                         ),
                        useShinyalert())
             ))
    )
)

Server:

server <- function(input, output) {
  
  ## Code for Panel 1
  
  df1 <- eventReactive(input$update, {
    input$df1$datapath
  })
  
  df1sheet <- eventReactive(input$update, {
    input$df1sheet
  })
  
  data1 <- reactive({
    req(input$df1)
    req(df1sheet())
    read_excel(df1(), sheet = df1sheet())
  })
  
  output$table1 <- renderTable({data1()}) 
  
  ## User can press on actionButton (id: download), and shinyalert will pop up, asking 
  ## for a filename input. After pressing confirmButton, runjs will click on 
  ## downloadButton and trigger downloadHandler.

  observeEvent(input$download, {
    shinyalert("Save as:", 
               type = "input",
               size = "xs", 
               closeOnEsc = TRUE, 
               closeOnClickOutside = TRUE, 
               showConfirmButton = TRUE, 
               showCancelButton = TRUE,
               confirmButtonText = "Save", 
               confirmButtonCol = "#0075B8",
               animation = TRUE)
  })
  
  output$downloadtable <- downloadHandler(
    filename = function () {paste(input$shinyalert, ".csv", sep = "")}, 
    content = function(file) {write.csv(data1(), file)}
  )
  
  observeEvent(input$shinyalert, {
    if (input$shinyalert != FALSE) {
      shinyjs::runjs("$('#downloadtable')[0].click();")
    }
  })
  
  ## Code for Panel 2
  
  df2 <- eventReactive(input$update2, {
    input$df2$datapath
  })
  
  df2sheet <- eventReactive(input$update2, {
    input$df2sheet
  })
  
  data2 <- reactive({
    req(input$df2)
    req(df2sheet())
    read_excel(df2(), sheet = df2sheet())
  })
  
  output$table2 <- renderTable({data2()}) 
  
  ## User can press on actionButton (id: download), and shinyalert will pop up, asking 
  ## for a filename input. After pressing confirmButton, runjs will click on 
  ## downloadButton and trigger downloadHandler.

  observeEvent(input$download2, {
    shinyalert("Save as:", 
               type = "input",
               size = "xs", 
               closeOnEsc = TRUE, 
               closeOnClickOutside = TRUE, 
               showConfirmButton = TRUE, 
               showCancelButton = TRUE,
               confirmButtonText = "Save", 
               confirmButtonCol = "#0075B8",
               animation = TRUE,
               inputId = "shinyalert2")
  })
  
  output$downloadtable2 <- downloadHandler(
    filename = function () {paste(input$shinyalert2, ".csv", sep = "")}, 
    content = function(file) {write.csv(data2(), file)}
  )
  
  observeEvent(input$shinyalert2, {
    if (input$shinyalert2 != FALSE) {
      shinyjs::runjs("$('#downloadtable2')[0].click();")
    }
  })
}

Solution

  • Your second downloadButton in conditionalPanel seems to be the issue.

    Replace

                     conditionalPanel(
                       "false",
                       downloadButton("downloadtable2")
                     ),
    

    with this

    downloadButton("downloadtable2", "Download", style = "visibility: hidden;")