Download Handler not working in Shiny app

I can't seem to get my download handler to work. My table is displaying the contents of two different tables in a database based on the input selected by the user. I'm very new to shiny and R and I'm not sure if I'm doing this right or how to fix this so you can actually download the contents of the table.

                     tabPanel(
                        "Study Results",
                        br(),
                        selectInput("resultsDisplay", "Display results by", choices = c("Single Study", "Compare Studies")),
                        uiOutput("resultsPnoDropUI"),
                        selectInput("resultsType", "Results Type", choices = c("results_mn", "results_pairwise")),
                        
                        downloadLink("downloadResults", "Download this File"),
                        br(),
                        br(),
                        DT::dataTableOutput("studyResultsTable")
                        
                    )
                    
        )
    })
    
    #Database Connections and reading tables
    protocolDB <-dbConnect(RSQLite::SQLite(), "clin_oral.db")
    resultsDB <- dbConnect(RSQLite::SQLite(), "OralCareResults.sqlite")
    results_mn <- dbReadTable(resultsDB, "Means")
    pairTable <- dbReadTable(resultsDB, "Pairwise")
    
    #Results DT Output
    output$studyResultsTable = DT::renderDataTable({
        resultTable <-dat<- get(input$resultsType)
    })
    
    #Download Results Table
    
    output$downloadResults <-downloadHandler(
        filename = function(){
            paste("study_results_download_", Sys.Date(), ".csv", sep="")
        },
        content = function(file){
            write.csv(resultTable, file)
        }
    )

Maybe add error message or log will be helpful more.

Anyway, I think resultTable object is not defined inside output$downloadResults <- ~~~.
Since resultTable is only defined in output$studyResultsTable

I'm not sure about whether this is caused by scoping problem.

Try define resultTable ( or dat also ) in server area and render it

resultTable <- dat <- get(input$resultsType)

output$studyResultsTable <- ~~~.
output$downloadResults <- ~~~.

You may want to see this article about scoping rule

When I tried that, I got the following error:

Error in .getReactiveEnvironment()$currentContext() :
Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.)

before check downloadResults, I wonder studyResultsTable works well ( sorry I'm not familiar with get).

I think it's good to wrap both studyResultsTable and downloadResults with single observeEvent

observeEvent(input$resultsType, {

resultTable <- dat <- input$resultsType
 output$studyResultsTable = DT::renderDataTable({
        resultTable
    })
    
    #Download Results Table
    
    output$downloadResults <-downloadHandler(
        filename = function(){
            paste("study_results_download_", Sys.Date(), ".csv", sep="")
        },
        content = function(file){
            write.csv(resultTable, file)
        }
    )

})

resultsTable can't be a regular R variable since it is going to change over the lifetime of your app. Instead it needs to be a reactive, which you then refer to when rendering the table and handling the download:

resultsTable <- reactive(get(input$resultsType))

output$studyResultsTable <- DT::renderDataTable(resultsTable())

output$downloadResults <- downloadHandler(
  filename = function() {
    paste0("study_results_download_", Sys.Date(), ".csv")
  },
  content = function(file) {
    write.csv(resultsTable(), file)
  }
)

You might find it helpful to read something about the basics of reactivity, like https://mastering-shiny.org/basic-reactivity.html.

1 Like

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.