Demo
Introduction
I hope nobody is reading. But if you are, then keep this to yourself.
Oftentimes you have a large dataset that takes a while to download. To give your users a visual cue that the download is in progress, you can (and should) add spinners to your download buttons.
The module
Let’s first create a basic download button module that we can build upon.
We’ll create an action button that will trigger the download (Yes, you read that right, an action button).
We’ll then add the real download button but it will be hidden.
R/mod_dnld_ui.R
#' Download button module UI
#' @param id Module ID
#' @return [shiny::tagList()]
<- function(id) {
mod_dnld_ui <- shiny::NS(id)
ns
::tagList(
shiny# Trigger button:
::actionButton(
shinyinputId = ns("actbtn"),
label = htmltools::doRenderTags(
::tags$span(
shiny::icon("download"),
shiny"Download"
)
)
),
# Real download button:
::downloadButton(
shinyoutputId = ns("dnld"),
label = NULL,
style = "visibility: hidden;"
)
) }
The basic server piece is also as simple:
R/mod_dnld_server.R
#' Download button module server
#' @param id Module ID
#' @param given_data Data to download, as a reactive.
#' @param filename Filename to use for download.
#' @return NULL
<- function(
mod_dnld_server
id,given_data = reactive({iris}),
filename = "iris.csv"
) {stopifnot(
"`given_data` must be a reactive" = is.reactive(given_data)
)
::moduleServer(
shinyid = id,
module = function(input, output, session) {
$dnld <- downloadHandler(
outputfilename = filename,
content = function(file) {
write.csv(given_data(), file)
}
)
}
) }
It takes in a reactive data object (given_data
) and a filename
. The rest is normal stuff.
We can now move on to adding the download button spinner.
Putting it all together
Now that we have the module UI and server parts, we can put them together in a shiny app.
The app is as simple as it can get:
<- bslib::page(
ui theme = bslib::bs_theme(version = 5),
::useShinyjs(),
shinyjs
::tags$div(
shinyclass = "bg-light",
::tags$div(
shinyclass = paste(
"container min-vh-100",
"d-flex justify-content-center align-items-center bg-white"
),
# module UI:
::tags$div(
shinymod_dnld_ui("this")
)
)
)
)
<- function(input, output, session) {
server # module server:
mod_dnld_server("this")
}
::shinyApp(ui, server) shiny
The full code is available on this GitHub Gist.