I'm struggeling with this one for hours:
In my app a simple test dataset df
gets loaded upon starting the app. The user then may add further datasets through a file upload before selecting from a dropdown menu (here selectInput
) the dataset he likes to continue working with.
What I'm failing to do:
After starting the app, the reactive df_list
should only contain the initial dataset df
and the dropdown menu should only hold the values c("", "df")
. After adding a dataset through an upload (or else) df_list
should be expanded (and the dropdown accordingly). So that I have a list containing all available datasets the user can select from.
But I only manage to create two scenarios: the dropdown menu contains df
but I fail to expand the df_list
after adding a dataset. Or the dropdown menu stays empty until I add a dataset, so the user has first to add a dataset before he can work with the test dataset.
My code example: I 'simulate' a file upload via an actionButton that creates the data.frame df_upload
. Here follows the example without trying to expand df_list
with the additional dataset df_upload
.
library(shiny)
# df available from start
df <- data.frame(Var = 1:10)
ui <- fluidPage(
selectInput("select", label = "Select data", choices = c("")),
actionButton("upload", "Simulate Upload"),
tableOutput("tabdata")
)
server <- function(input, output, session) {
# reactive that lists all datasets
df_list <- reactive({list(df = df)})
# 'upload' of second df
df_upload <- eventReactive(input$upload, {
data.frame(Var = 11:20)
})
# observes if df_list() gets expanded to update choices
observeEvent(df_list(), {
updateSelectInput(session = session,
inputId = "select",
choices = c("", names(df_list())))
})
# output of selected dataset
output$tabdata <- renderTable({
req(df_list())
df_list()[[input$select]]
})
}
shinyApp(ui, server)
Here one of many things I tried (this adds df_upload
succesfully, but fails to show df
initially in the dropdown menu after starting the app):
library(shiny)
# df available from start
df <- data.frame(Var = 1:10)
ui <- fluidPage(
selectInput("select", label = "Select data", choices = c("")),
actionButton("upload", "Simulate Upload"),
tableOutput("tabdata")
)
server <- function(input, output, session) {
# reactive that lists all datasets
df_list <- reactive({
df_list <- list(df = df)
# check if there is an uploaded df, and if yes add it to df_list
# does not work, because it does not give me df_list only containing df
# in case no dataset was added yet.
# is.null is not the proper way, because if df_upload does not exist yet,
# it does not yield NULL. I also tried it unsuccessfully
# with exists("df_upload()")
if (!is.null(df_upload())) {
df_list[[2]] <- df_upload()
names(df_list)[2] <- "df_upload"
}
return(df_list)
})
# 'upload' of second df
df_upload <- eventReactive(input$upload, {
data.frame(Var = 11:20)
})
# observes if df_list() gets expanded to update choices
observeEvent(df_list(), {
updateSelectInput(session = session,
inputId = "select",
choices = c("", names(df_list())))
})
# output of selected dataset
output$tabdata <- renderTable({
req(df_list())
df_list()[[input$select]]
})
}
shinyApp(ui, server)
A simple solution using reactiveValues based on @Limey's comment:
library(shiny)
# df available from start
df <- data.frame(Var = 1:10)
reactlog::reactlog_enable()
ui <- fluidPage(
selectInput("select", label = "Select data", choices = c("df")),
actionButton("upload", "Simulate Upload"),
tableOutput("tabdata")
)
server <- function(input, output, session) {
# empty reactiveValues rv to store all datasets in
rv <- reactiveValues()
# store the test df in rv
rv$df <- df
# 'upload' of second df and storing it in rv
observeEvent(input$upload, {
rv$df_upload <- data.frame(Var = 11:20)
})
# update selectInput choices
observe({
updateSelectInput(session = session,
inputId = "select",
choices = names(rv),
selected = "df")
})
# output of selected dataset
output$tabdata <- renderTable({
rv[[input$select]]
})
}
shinyApp(ui, server)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.