Carlos Xavier Bonilla
Carlos Xavier Bonilla

Reputation: 667

Have downloadButton work with observeEvent

I want to add functionality that gives the user feedback once they click downloadButton in my shiny app (e.g., it gives the user an alert message or toggles ui elements once clicked). Essentially, I want to be able to have downloadButton download some data and behave like actionButton, so that it responds to event triggers. Is this possible? This is how I have my code set up:

ui <- fluidPage(
  useShinyjs(),

  downloadButton("download", "Download some data")
)

server <- function(input, output, session) {

  observeEvent(input$download, {  # supposed to alert user when button is clicked
    shinyjs::alert("File downloaded!")  # this doesn't work
  })

  output$download <- downloadHandler(  # downloads data
    filename = function() {
      paste(input$dataset, ".csv", sep = "")
    },
    content = function(file) {
      write.csv(mtcars, file, row.names = FALSE)
    }
  )

}

shinyApp(ui = ui, server = server)

This only seems to work if I change downloadButton to an actionButton element in the ui, but doing this disables the download output.

Upvotes: 9

Views: 4065

Answers (2)

Carlos Xavier Bonilla
Carlos Xavier Bonilla

Reputation: 667

Based on divibisan's answer above, I was able to trigger events by nesting rv$download_flag within an if statement in the downloadHandler:

  # Create reactiveValues object
  # and set flag to 0 to prevent errors with adding NULL
  rv <- reactiveValues(download_flag = 0)

  output$download <- downloadHandler(  # downloads data
    filename = function() {
      paste(input$dataset, ".csv", sep = "")
    },
    content = function(file) {
      write.csv(mtcars, file, row.names = FALSE)
      # When the downloadHandler function runs, increment rv$download_flag
      rv$download_flag <- rv$download_flag + 1

      if(rv$download_flag > 0){  # trigger event whenever the value of rv$download_flag changes
        shinyjs::alert("File downloaded!")
      }

    }
  )

Upvotes: 4

divibisan
divibisan

Reputation: 12155

It's a bit of a hack, but you can have the downloadHandler function modify a reactiveValue that acts a flag to trigger the observe event:

# Create reactiveValues object
#  and set flag to 0 to prevent errors with adding NULL
rv <- reactiveValues(download_flag = 0)

# Trigger the oberveEvent whenever the value of rv$download_flag changes
# ignoreInit = TRUE keeps it from being triggered when the value is first set to 0
observeEvent(rv$download_flag, {
    shinyjs::alert("File downloaded!")
}, ignoreInit = TRUE)

output$download <- downloadHandler(  # downloads data
    filename = function() {
        paste(input$dataset, ".csv", sep = "")
    },
    content = function(file) {
        write.csv(mtcars, file, row.names = FALSE)
        # When the downloadHandler function runs, increment rv$download_flag
        rv$download_flag <- rv$download_flag + 1
    }
)

Upvotes: 7

Related Questions