Home > Blockchain >  R - shiny's downloadHandler() returns an empty HTML file if a condition is not met
R - shiny's downloadHandler() returns an empty HTML file if a condition is not met

Time:08-04

I want users to download a file from my shiny app. However, if they don't input correctly certain parameters inside a textInput() widget (e.g. a correct e-mail), I want to stop the download and display a notification (through the use of the functionalities of shinyjs for example).

However, if I put an if statement inside the content argument of downloadHandler(), if the condition is not met, the button fires the download anyway, but the result is just an empty HTML file reporting a 404 error. I've slightly modified the Shiny example showing the use of downloadHandler() to report this behaviour:


library(shiny)
library(tidyverse)

# UI
ui <- fluidPage(
  
  textInput(input = "text",
            label = "Write 'download' to download the correct file"),
  
  br(),
  
  downloadButton(outputId = "downloadData",
                 label = "Download")
  
)

# SERVER
server <- function(input, output) {
  
  data <- mtcars
  
  output$downloadData <- downloadHandler(
    
    filename = function() {
      
      paste("data-", Sys.Date(), ".csv", sep = "")
      
    },
    
    content = function(file) {
      
      if (input$text == "download") {
        
        write.csv(x = data,
                  file =  file)
        
      }
      
    }
    
  )
  
}

shinyApp(ui, server)

Two scenarios will possibly solve the problem:

a) avoid the download of the HTML file reporting the error;
b) display a notification that does not constantly update each time I write something wrong in the text input until the right text is added.

Thanks in advance for your help!

CodePudding user response:

To expand on my comment above:

library(shiny)
library(tidyverse)
library(shinyjs)

# UI
ui <- fluidPage(
  useShinyjs(),
  textInput(input = "text",
            label = "Write 'download' to download the correct file"),
  br(),
  downloadButton(outputId = "downloadData", label = "Download")
)

# SERVER
server <- function(input, output) {
  data <- mtcars
  
  observeEvent(input$text, {
    if (input$text == "download") {
      enable("downloadData")
    } else {
      disable("downloadData")
    }
  })
  
  output$downloadData <- downloadHandler(
    filename = function() {
      paste("data-", Sys.Date(), ".csv", sep = "")
    },
    content = function(file) {
        write.csv(x = data, file =  file)
    }
  )
}

shinyApp(ui, server)

Giving

enter image description here

and

enter image description here

[Note the change in font colour on the Download widget.]

Edit

In response to OP's request in the comments below, to use the shinyFeedback package...

  1. Load the package and add the necessary call to the UI definition:
...
library(shinyFeedback)

# UI
ui <- fluidPage(
  useShinyjs(),
  useShinyFeedback(), ...
  1. Modify the observeEvent that watches the textInput:
  observeEvent(input$text, {
    if (input$text == "download") {
      hideFeedback("text")
      enable("downloadData")
      showFeedbackSuccess("text", "Ready to download")
    } else {
      disable("downloadData")
      showFeedbackDanger("text", "Please enter the password")
    }
  })

This gives

enter image description here

and

enter image description here

  • Related