I'm building an R Shiny app that acts as a GUI for a simulation model my team has built. The user defines parameters, clicks run, and the model produces a bunch of charts and tables as output. My problem is, every time the user opens the app they have to enter in their parameters again. I'd like them to be able to save their parameters and bring them up again when they go back to the app.
My initial approach was to have the user download the parameters in a csv using downloadHandler to their local machine, and then upload them in their next session. This is not workable because there is too much risk that the formatting will get messed up or the user will make changes to the file, and then I'll have errors when they upload it again.
What I think makes the most sense is to save the parameters in a file on the server (I'd prefer an .Rdata file, so I can save the parameters in lists), and use a selectInput widget to allow the user to call up the parameter file they want. I have no idea how to save to the server from within a Shiny app, or how to get downloadHandler to do this.
EDIT For example, when I do this: UI:
downloadLink("saveParams",label="Save Your Model")
Server:
output$saveParams <- downloadHandler(
filename <- function(){
paste0(input$nameModel,".RData")
},
content = function(file) {
inputparams<-inputparams()
save(inputparams, file = file)
}
)
It gives the user the option of where to save the file, which I want to avoid. I want it automatically to drop it onto the server. I tried using an actionButton to trigger a reactive that used save
but couldn't get it to run.
Any suggestions?
Here is a working example, using a textInput
and actionButton
to save, and a selectInput
to load the file. Note that /home/user
is a folder that your shiny app has write permission to. You might need more sophisticated validation to ensure that user enters a valid file name.
If you have multiple users for your Shiny app, you'll also need to find a way to ensure that one user will not overwrite the other's saved file (for example, prefix with user's name, suffix with current time, etc), but that is outside the scope of this question.
ui.R
library(shiny)
shinyUI(fluidPage(
# Application title
titlePanel("Old Faithful Geyser Data"),
# Sidebar with a slider input for number of bins
sidebarLayout(
sidebarPanel(
sliderInput("bins",
"Number of bins:",
min = 1,
max = 50,
value = 30),
textInput("save_file", "Save to file:", value="sample.RData"),
actionButton("save", "Save input value to file"),
uiOutput("load")
),
# Show a plot of the generated distribution
mainPanel(
plotOutput("distPlot")
)
)
))
server.R
library(shiny)
shinyServer(function(input, output, session) {
# render a selectInput with all RData files in the specified folder
output$load <- renderUI({
choices <- list.files("/home/user", pattern="*.RData")
selectInput("input_file", "Select input file", choices)
})
# Save input$bins when click the button
observeEvent(input$save, {
validate(
need(input$save_file != "", message="Please enter a valid filename")
)
bins <- input$bins
save(bins, file=paste0("/home/user/", input$save_file))
choices <- list.files("/home/user", pattern="*.RData")
updateSelectInput(session, "input_file", choices=choices)
})
# Load an RData file and update input
observeEvent(input$input_file, {
load(paste0("/home/user/",input$input_file))
updateSliderInput(session, "bins", value=bins)
})
output$distPlot <- renderPlot({
# generate bins based on input$bins from ui.R
x <- faithful[, 2]
bins <- seq(min(x), max(x), length.out = input$bins + 1)
# draw the histogram with the specified number of bins
hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
})
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