I know that there is quite some material already available on the web to answer my question but none of them seem to work for me. I suppose that's because I do not understand Shiny's reactive programming well.
So, I wish to create an interface that lets a user select a file using fileInput
and upload it only on clicking the Upload button. I tried a few solutions from various forums but none worked. Following is my latest attempt:
#ui.R
library(shiny)
shinyUI(pageWithSidebar(
headerPanel(""),
sidebarPanel(
fileInput("in_file", "Input file:",
accept=c("txt/csv", "text/comma-separated-values,text/plain", ".csv")),
checkboxInput(inputId="is_header", label="Does the input file have column names?", value=TRUE),
actionButton("upload_data", "Upload Data"),
),
mainPanel(
tabsetPanel(
tabPanel("Original Data", tableOutput("orig_data"))
)
)
))
#server.R
library(shiny)
shinyServer(function(input, output, session) {
ra_dec_data <- reactive({
if(input$upload_data==0)
return(NULL)
return(isolate({
head(read_data(input$in_file$datapath, input$in_file$is_header), 50)
}))
})
output$orig_data <- renderTable({
ra_dec_data()
})
})
The issue I face is that the file gets uploaded as soon as it is selected and the Upload button is unresponsive.
My guess is that what I have done does not make sense, so please accept my apologies for doing this terribly. Any help would be really appreciated. Thanks!
fileInput
upload the file directly so I suggest you to create your own "fileInput".
Here is how I shall proceed :
Server.R
library(shiny)
shinyServer(function(input, output, session) {
observe({
if (input$browse == 0) return()
updateTextInput(session, "path", value = file.choose())
})
contentInput <- reactive({
if(input$upload == 0) return()
isolate({
writeLines(paste(readLines(input$path), collapse = "\n"))
})
})
output$content <- renderPrint({
contentInput()
})
})
Ui.R
library(shiny)
shinyUI(pageWithSidebar(
headerPanel("Example"),
sidebarPanel(
textInput("path", "File:"),
actionButton("browse", "Browse"),
tags$br(),
actionButton("upload", "Upload Data")
),
mainPanel(
verbatimTextOutput('content')
)
))
In "Server.R" firstly we update the value of the text input each time the action button "Browse" is clicked.
"contentInput" is a reactive function, it will be reexecuted when input values (contained in the body of the function) are changed, "input$upload" here, and not when "input$path" changed because we isolate it. If we didn't isolate the part containing "input$path", the "contentInput" will be reexecuted each times we browse a new file and then the upload button will be useless here.
And then we return the result of "contentInput" in "output$content".
Hope this help.
I realized that if you cancel the file choosing it produce an error and the shiny app crash, then you should use this function by Henrik Bengtsson (https://stat.ethz.ch/pipermail/r-help/2007-June/133564.html) :
file.choose2 <- function(...) {
pathname <- NULL;
tryCatch({
pathname <- file.choose();
}, error = function(ex) {
})
pathname;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With