Search code examples
rshinyshinyalert

ShinyAlert as input inside downloadHandler


Is there a way to use Shinyalert() as a filename input for downloadHandler()? I want to create an app where the user can download the plot, and a "save as:" pop-up input message will appear. Then the file will be saved as whatever the input is.

I tried doing this with ShinyAlert but even though I got the pop-up input message, the file was downloaded the instant I pressed on the download button. Here's what I have so far:

UI:

ui <- fluidPage(
  useShinyalert(),
  plotOutput("vmgraph"),
  downloadButton("downloadPlot", "Download Plot")
) 

Server:

server <- function(input, output) {

output$vmgraph <- renderPlot({vmgraph()})

rv <- reactiveValues(download_flag = 0)
  
output$downloadPlot <- downloadHandler(
    filename = function(){
      rv$download_flag <- rv$download_flag + 1
      if (rv$download_flag > 0) {
        shinyalert("Save as:", 
                   type = "input", 
                   size = "m", 
                   closeOnEsc = TRUE, 
                   closeOnClickOutside = TRUE, 
                   showConfirmButton = TRUE, 
                   showCancelButton = TRUE,
                   confirmButtonText = "Save", 
                   confirmButtonCol = "#0075B8",
                   animation = TRUE)
      }
      paste(input$shinyalert, ".png", sep = "")},
    content = function(file) {
      ggsave(file, plot = vmgraph(), width = 12, height = 7.7)
    }
  )

I use download_flag to act as a trigger for Shinyalert(). Been trying to find a way for this to work for hours so any help will be appreciated.


Solution

  • I got something close to what you want. Key is using html=TRUE and putting a tagList inside the shinyalert, in order to make the "confirm" button the downloadButton(), and then using some javascript:

    library(shiny)
    library(shinyalert)
    library(ggplot2)
    library(shinyjs)
    
    ui <- fluidPage(
      useShinyjs(),
      useShinyalert(),
      plotOutput("vmgraph"),
      actionButton("downloadPlot", "Download Plot")
    ) 
    
    server <- function(input, output) {
      
      output$vmgraph <- renderPlot({plot(mtcars)})
      
      observeEvent(input$downloadPlot, {
        shinyalert("Save as:", 
                   type = "info",
                   size = "m",
                   html = TRUE,
                   text = tagList(
                     textInput(inputId = "name", label = NULL ),
                     downloadButton("confName", "Confirm")
                   ),
                   closeOnEsc = TRUE,
                   closeOnClickOutside = TRUE,
                   showConfirmButton = FALSE,
                   showCancelButton = TRUE,
                   animation = TRUE
        )
        runjs("
            var confName = document.getElementById('confName')
            confName.onclick = function() {swal.close();}
            ")
      })
      
      output$confName <- downloadHandler(
        filename = function(){
          paste(input$name, ".png", sep = "")},
        content = function(file) {
          ggsave(file, plot = plot(mtcars), width = 12, height = 7.7)
        }
      )
    
    }
      
    shinyApp(ui, server)