-
Notifications
You must be signed in to change notification settings - Fork 1.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
downloadButton does not work on startup if hidden, downloads html of app instead, improve docs to clarify. #4191
Comments
It's a normal behavior in HTML +css. You have to activate the element and make it invisible with a display duration of 0 seconds. library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
tags$head(
tags$style(type = "text/css", HTML(".texte_code {
font-family: Courier New,Courier,Lucida Sans Typewriter,Lucida Typewriter,monospace;
font-weight: 400;
}")),
tags$style(type = "text/css", HTML(".display_none {
display: none;
}")),
tags$style(type = "text/css", HTML(".display_inline {
display: inline;
}")),
tags$style(type = "text/css",
HTML(paste0("
.active_invisible { animation: animeHiddend 0s linear 0s 1 normal forwards;
height: 0px;}
")
)
)
),
h3("works :"),
downloadButton("downloadData1", "downloadData1"),
h3("doesn't work "),
splitLayout(
actionButton("BtndownloadData2",HTML("See downloadData2 <span class='texte_code'>display: none</span>")),
div(id="divDownloadData2",
downloadButton("downloadData2", "downloadData2"),
class="display_none"
),
cellWidths =c("25%","25%")
),
h3("works :"),
splitLayout(
actionButton("BtndownloadData3",HTML("See downloadData3 <span class='texte_code'>.active_invisible</span>")),
div(id="divDownloadData3",
downloadButton("downloadData3", "downloadData3"),
class="active_invisible"
),
cellWidths =c("25%","25%")
)
)
server <- function(input, output) {
data <- mtcars
output$downloadData1 <- downloadHandler(
filename = function() {
paste("data-", format(Sys.time(),'%Y-%m-%d_%H-%M-%S'), ".csv", sep="")
},
content = function(file) {
write.csv(data, file)
}
)
output$downloadData2 <- downloadHandler(
filename = function() {
paste("data-", format(Sys.time(),'%Y-%m-%d_%H-%M-%S'), ".csv", sep="")
},
content = function(file) {
write.csv(data, file)
}
)
output$downloadData3 <- downloadHandler(
filename = function() {
paste("data-", format(Sys.time(),'%Y-%m-%d_%H-%M-%S'), ".csv", sep="")
},
content = function(file) {
write.csv(data, file)
}
)
observeEvent(input$BtndownloadData2,{
shinyjs::removeClass(id="divDownloadData2", class="display_none")
shinyjs::addClass(id="divDownloadData2", class="display_inline")
},ignoreInit=TRUE )
observeEvent(input$BtndownloadData3,{
shinyjs::removeClass(id="divDownloadData3", class="active_invisible")
shinyjs::addClass(id="divDownloadData3", class="display_inline")
},ignoreInit=TRUE )
}
shinyApp(ui, server) |
Yes, I guessed there were some tricks, but most of us using shiny are not front end developers, so a minimum of documentation would be great to at least be aware of these behaviors. From my back-end background, it makes no sense that this is the default behavior. It breaks all the rules of documentation for hidden optimizations, which should always be clear to the reader of the documentation. For normal back-end code things are clear, while Shiny has dragged me down in 20-hour rabbit holes more times than I can remember. I just want to suggest a small snippet is added to the docs of downloadButton for future users, to avoid this one at least. |
Same for me : I learned this « normal behavior » at my beginning in R Shiny 7 years ago during some long hours. This is not specific to For example it can happen for some elements behind unselected tabs ( Also for But Shiny is simpler than others tools when you don't know UI: the learning curve is more easy. I learnt CSS+ web UI with Shiny. |
To not make this thread stall, here are 3 options:
Which one do you prefer ? |
You have to wait for the Shiny team's response :) PS: I'm a simple user. |
I think that it's not obvious that |
Here's a smaller reprex showing how to use library(shiny)
library(shinyjs)
ui <- fluidPage(
useShinyjs(),
h3("Hidden Download Button Issue #4191"),
# Button to trigger the download, but not via the download button
actionButton("do_download", "Do the Download"),
# Hidden download button
div(
id = "download_div",
downloadButton("download_data", "Download Data"),
style = "display: none"
)
)
server <- function(input, output) {
output$download_data <- downloadHandler(
filename = function() {
paste("data-", format(Sys.time(), '%Y-%m-%d_%H-%M-%S'), ".csv", sep = "")
},
content = function(file) {
write.csv(mtcars, file)
}
)
outputOptions(output, "download_data", suspendWhenHidden = FALSE)
observeEvent(input$do_download, {
shinyjs::click("download_data")
})
}
shinyApp(ui, server) |
@Roleren I've proposed a documentation update in #4196. It's a little different than what you suggested for two reasons:
|
Just spent 12 hours coding a single button of a shiny (modular) app and it turned out shiny disables my hidden buttons on default, why would it disable programmatic clicks on a hidden download button ?
Could we maybe add a note to docs of downloadButton {shiny} that simply states:
"Shiny by default disables programmatic clicks for hidden downloadButtons, use: output options(output, "my_button_id", suspendWhenHidden = FALSE) to suppress this behavior"
Will save future versions of myself in alternate universes a lot of time.
Thank you.
The text was updated successfully, but these errors were encountered: