I am working on an app for educational purposes that is supposed to show plots of data uploaded by the user. The user is asked to upload a csv file and then to select two variables from said file which will be plotted. I have provided the code for two data files which can be used with the repex: uniformData.csv contains two columns of data from uniform distributions and a grouping column; normalData.csv contains two columns of data from normal distributions and a grouping column. In the example I am describing below I first upload uniformData.csv, select the x_unif and the y_unif variables for plotting, then upload the normalData.csv.
Since the idea was that the user can try out multiple data files if they wish, I update the selectInput control options of my app with an observeEvent() and updateSelectInput() every time the user uploads a new data file. This works fine. I want to let the user pick the variables of their choice and thus I have set selected = character(0) in my calls to updateSelectInput(). I do not want the first column of the uploaded data file to be automatically selected, because I want the user to consciously choose their x and y variables.
The first cycle of the app works fine. I can upload a data file (e.g. uniformData.csv), select an x (x_unif) and a y (y_unif) variable and the plot gets generated. However, problems arise when a new file is uploaded. I upload a data file, the choices for the two selectInput controls get updated but the value of the selectInput does not get set to character(0). The value of input$x as well as the value of input$y do not change after a new data file has been uploaded. The value of input$x is still "x_unif" and the value of input$y remains "y_unif" (if one uploads the uniformData.csv and selects the respective x and y variables). I thought that setting selected = character(0) would set the value of input$x and input$y to "".
Within the repex I print the value of the selectInput with the inputID of "x" with verbatimTextOutput(). You can find it right above the plotting area. There you can see that even after uploading the second file, the value of input$x does not change to "" as I thought it would. The plot does not throw an error since I use req(x(), y()) within renderPlot() to catch any inputs that are not truthy (if I don't use req() I would get an error after uploading the second data file).
Does anyone know of a way to set input$x and input$y = "" with updateSelectInput() or with some other method? I unfortunately know zero JavaScript, which might solve the issue? I would be grateful for any ideas and thank you in advance.
library(shiny)
ui <- fluidPage(fluidRow(
column(
width = 4,
fileInput(
inputId = "file",
label = "Upload your datafile",
accept = ".csv"
),
selectInput(
inputId = "x",
label = "Select x variable:",
choices = NULL
),
selectInput(
inputId = "y",
label = "Select a y variable",
choices = NULL
)
),
column(
width = 8,
verbatimTextOutput("selectInputVal"),
plotOutput("plot")
)
))
server <- function(input, output, session) {
data <- reactive({
req(input$file)
read.table(
input$file$datapath,
sep = ",",
dec = ".",
header = TRUE
)
})
observeEvent(eventExpr = input$file,
handlerExpr = {
updateSelectInput(session,
"x",
choices = names(data()),
selected = character(0))
updateSelectInput(session,
"y",
choices = names(data()),
selected = character(0))
})
x <- reactive({
req(data())
req(input$x)
data()[[input$x]]
})
y <- reactive({
req(data())
req(input$y)
data()[[input$y]]
})
output$selectInputVal <- renderPrint(input$x)
output$plot <- renderPlot({
req(x(), y())
plot(x(), y())
})
}
runApp(shinyApp(ui = ui, server = server))
# Create example data filies:
RNGversion("4.1.0")
set.seed(123)
normalData <- data.frame(
x_norm = rnorm(n = 10, mean = 100, sd = 15),
y_norm = rnorm(n = 10, mean = 50, sd = 10),
grp_ab = sample(c("a", "b"), size = 10, replace = TRUE)
)
uniformData <- data.frame(
x_unif = runif(n = 20, min = 0, max = 10),
y_unif = runif(n = 20, min = -10, max = 10),
grp_cd = sample(c("c", "d"), size = 20, replace = TRUE)
)
# write.csv(normalData, "normalData.csv", quote = FALSE, row.names = FALSE)
# write.csv(uniformData, "uniformData.csv", quote = FALSE, row.names = FALSE)


