How to print a message in the app after the user forgets to upload a file?


#1

Hello!

I am building a rudimentary shiny app. First, I created a data frame ‘x’ and saved it in my working directory (where my code for my app is):

x <- data.frame(a = 1:4, b = 2:5)
write.csv(x, 'x.csv', row.names = F)

In my shiny app I’d like to:

  1. Upload file ‘x.csv’
  2. Click my action button ‘Click Here’ and run a few commands upon clicking it.
  3. Get a message printed in the Shiny app itself: “Load a file!” if I click on my button “Click here” after forgetting to upload the file first.

My code works, but I can’t figure out how to make my message appear.
Thank you so much for your suggestions!

My code:

library(shiny)

ui <- fluidPage(
  br(),
  # User should upload file x here:
  fileInput("file_x", label = h5("Upload file 'x'!")),
  br(),
  # Users clicks the button:
  actionButton("do_it", "Click Here"),
  br(),
  # Print last value of the button 'do_it':
  verbatimTextOutput("print_action")
)


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

observeEvent(input$do_it, {

# Just a check of my button's actions:
output$print_action <- renderPrint({input$do_it})

# Validating the input - next 5 lines are not working:
# validate(
#   need(
#     try(is.null(input$file_x), "Load a file!")
#     )
# )

# Reading in the file:
fileData <- reactive({
  infile <- input$file_x
  if (is.null(infile)) {
    return(NULL)
  }
  read.csv(infile$datapath)
})
x <- fileData()

# Writing out the same file - but under a different name:
filename <- paste0("x", input$do_it, ".csv")
write.csv(x, file = filename, row.names = FALSE)

})
}

shinyApp(ui, server)

#2

This isn’t too complicated with shinyjs. You need to include a hidden p element in the ui and unhide it when the file hasn’t been selected yet. Code I’ve added is followed with ########## (10 #s)

library(shiny)
library(shinyjs)  ##########

ui <- fluidPage(
  # make shinyjs work in the UI  ##########
  useShinyjs(),                  ##########
  br(),
  # User should upload file x here:
  fileInput("file_x", label = h5("Upload file 'x'!")),
  br(),
  # Users clicks the button:
  actionButton("do_it", "Click Here"),
  hidden(p("Select a file first",                    ##########
           id = "p_nofile",                          ##########
           style = "font-weight:bold;color:red;")),  ##########
  br(),
  # Print last value of the button 'do_it':
  verbatimTextOutput("print_action")
)


server <- function(input, output, session) {
  
  observeEvent(input$do_it, {
    # If there file_x input is NULL, show the message in p_nofile  ##########
    if (is.null(input$file_x)){                                    ##########
      shinyjs::show("p_nofile")                                    ##########
    } else{                                                        ##########
      # if we have a file selected, hide the p_nofile message      ##########
      shinyjs::hide("p_nofile")                                    ##########
      
      # Just a check of my button's actions:
      output$print_action <- renderPrint({input$do_it})
      
      # Validating the input - next 5 lines are not working:
      # validate(
      #   need(
      #     try(is.null(input$file_x), "Load a file!")
      #     )
      # )
      
      # Reading in the file:
      fileData <- reactive({
        infile <- input$file_x
        if (is.null(infile)) {  
          return(NULL)     
        }
        read.csv(infile$datapath)
      })
      x <- fileData()
      
      # Writing out the same file - but under a different name:
      filename <- paste0("x", input$do_it, ".csv")
      write.csv(x, file = filename, row.names = FALSE)
    }    ##########
  })
}

shinyApp(ui, server)

#4

nutterb, thank you very much!
I tried your code. It’s working, but I have two questions:

  1. Is it possible to hide the (ui) text “Select a file first” - only after the user tries to click the button “Click Here” without uploading the file first?
  2. Is it possible to get rid of the text “Select a file first” after the user uploaded the file?
    Thanks again!

#5

I think my code sample already does that. This is what the app looks like when I first run it on my machine (I’ve made the background gray so you can see where the images end):

image

Then after clicking the button without selecting a file.

image

And then after clicking the button after selecting a file.

image

Is that the behavior you desire?


#6

Actually, it almost does what is desired, but not 100%. Assume I forget to upload a file and click on the “Click Here” button. Then I get the message. But once I upload the file, the message is still there - until I click on “Click Here” button. It’d be nice if it disappeared after the data file has been uploaded.