I have a shiny app and in this app a table that gives an overview over some items. I want to make it possible to the user to download these items by clicking on a button.
My current approach works somehow, but leads to a very stange behaviour if I modify seemingly unrelated parts.
Here is an explanation of my minimal example:
I have a list of two data.frames for which I want to offer download options. To achieve this, I make action buttons, that write the wanted data.frame to an input using an onclick event. When this textinput is changed, it triggers a shiny download button to download the wanted data.frame.
This approach seems pretty complicated, but usually it works great. It seems that the download-Button is complicating things.
library(shiny)
library(shinyjs)
ui <- fluidPage(
DT::dataTableOutput("dt"),
shinyjs::useShinyjs(),
div( # replace 'div' by 'hidden' and see what happens
"should not be visible to user",
textInput(inputId = "datasetToDownload", label = "Dataset to Download"),
downloadButton(outputId = "downloadButton")
)
)
datasetsToDownload <- c("iris", "mtcars")
server <- function(input, output, session) {
output$dt <- DT::renderDT({
df <- data.frame(
"datasets" = datasetsToDownload,
"download" = sapply(datasetsToDownload, function(id) {
as.character(actionButton(
inputId = paste0("download", id),
label = paste("download", id),
onclick = sprintf("Shiny.setInputValue('datasetToDownload', '%s', {priority: 'event'})", id)
))
})
)
DT::datatable(
df,
escape = setdiff(names(df), c("download"))
)
})
observeEvent(input$datasetToDownload,{
if (input$datasetToDownload %in% datasetsToDownload){
shinyjs::click("downloadButton")
}
})
output$downloadButton <- downloadHandler(
filename = function() {
# Use the selected dataset as the suggested file name
filename <- paste0(input$datasetToDownload, ".csv")
print("filename:")
print(filename)
filename
},
content = function(file) {
print("content")
print("file:")
print(file)
# Write the dataset to the `file` that will be downloaded
write.csv(get(input$datasetToDownload), file)
}
)
}
shinyApp(ui, server, options = list(launch.browser = TRUE))
This works fine, but when I hide the textInput
and downloadButton
, it downloads a 49aqnopL.htm
that is close to but not exactly equal to the html-code of the shiny app. Also the print statements inside the downloadHandler
do not happen. I find this behaviour very surprising. Do you know why this happens?
Also: Do you have any suggestion, how I can achieve my goal?
This is basically a duplicate of R Shiny - How to have an action button that automatically downloads a csv file (Not download button?)
Per that, switching to conditionalPanel("false")
instead of hidden()
solves the issue:
conditionalPanel(
"false",
"should not be visible to user",
textInput(inputId = "datasetToDownload", label = "Dataset to Download"),
downloadButton(outputId = "downloadButton")
)