Examples of putting downloadHandler in a function?


#1

I am building a complex dashboard with approximately 32 boxes showing different types of information. Some of the boxes display tables (rendered using knitr), some display plots (produced by ggplot). Regardless, each box gives users the option to download both the plot and a customized data set containing the plotted data (in a csv file).

I have individual downloadButtons and an instance of downloadHandler associated with each download. The code for these blocks follows the examples available in the shiny documentation. I’m not looking forward to maintaining 50 to 60 instances of the downloadHandler to manage all of the downloads.

Are there any examples of putting the downloadHandler in a wrapper function? Ideally, I’d like to pass an output parameter, a file name parameter and an output type parameter to the function.

Thanks in advance


#2

This sounds like a good scenario for the use of a module function. I did a blogpost about using modules for this kind of thing recently. The example doesn’t use downHandlers but you can incorporate any UI + Server combination to a module. Let me know if you have any questions!


#3

I think @paul’s point towards modules is definitely the right way to go. module documentation at shiny.rstudio.com is another place to explore modules, as well


#4

Thanks for the suggestion, Paul. I have created a function to create a downloadButton (called “downloadObjUI”) and a function containing the downloadHandler (called “downloadObj”). One question I have is how to link the “downloadObj” and “downloadObjUI”. How does one fire off downloadObj when a button created by downloadObjUI is clicked?

TIA


#5

The inputs from the UI module will then be linked to the server logic in your downloadObj funciton, provided you created an ns <- NS(id) variable in your UI function and wrapped inputs/outputs in the ns() function.

In your case:

downloadObjUI <- function(id, ...) {
  ns <- NS(id)

  downloadButton(n("data_download"), label = "Download Data")
}

Will link to something like this in downloadObj:

downloadObj <- function(input, output, session, ...) {
  
  output$chart_download <- downloadHandler(
    filename = function() {
      paste("data-", Sys.Date(), ".csv", sep="")
    },
    content = function(file) {
      write.csv(data, file)
    }
  )
}

So if you have a UI and accompanying server module setup like so, you can call the UI function within your UI code:

downloadObjUI(id = "download1", ...) 
# '...' denoting anythng else you need to pass to the module

Then in your server you call the server side module and pass the same id that you gave the UI module:

callModule(downloadObj, id = "download1", ...)

Let me know if that helps!


#6

Hi Paul,
Thanks. This worked without a hitch.
Cheers–
AB