Update Shiny's 'selectInput' dropdown with new values after uploading new data using fileInput
I added reactive object myData
that you have to use for table contents
, but more importantly to update choices in selectInput
(check observe
and updateSelectInput
part).
library(shiny)
ui <- shinyUI(
fluidPage(
fileInput("file1", "Choose file to upload", accept = ".rds"),
selectInput("myNames","Names", ""),
tableOutput("contents")
)
)
server <- function(input, output, session) {
myData <- reactive({
inFile <- input$file1
if (is.null(inFile)) {
d <- myDataFrame
} else {
d <- readRDS(inFile$datapath)
}
d
})
output$contents <- renderTable({
myData()
})
observe({
updateSelectInput(session, "myNames",
label = "myNames",
choices = myData()$names,
selected = myData()$names[1])
})
}
shinyApp(ui, server)
R-Shiny: Select input reactive on file input
updatedSelectInput should do it for you. Below is a minimal example.
To reduce package dependencies I switched to loading .csv rather than .xlsx. Note that the loaded file isn't validated, so if junk goes in you'll get junk out.
library(shiny)
#UI
ui <- fluidPage(
selectInput('mydropdown', label = 'Select', choices = 'No choices here yet'),
fileInput('myfileinput', label = 'Select File', accept = c(".csv"))
)
#Server
server <- function(input, output, session) {
observeEvent(input$myfileinput, {
mytable <- read.csv(input$myfileinput$datapath)
updateSelectInput(session, "mydropdown", label = "Select", choices = colnames(mytable))
})
}
shinyApp(ui = ui, server = server)
updateSelectInput does not update the input$id value of selectInput
The issue occurs because selectInput
cannot handle character(0)
as a valid selection since it is not listed in choices
but when multiple = FALSE
no selection possible either.
You can use selectizeInput
, set multiple = TRUE
which allows empty inputs but also limit it to only one selection via the maxItem
option
library(shiny)
ui <- fluidPage(fluidRow(
actionButton("browser", "Browser"),
column(
width = 4,
fileInput(
inputId = "file",
label = "Upload your datafile",
accept = ".csv"
),
selectizeInput(
inputId = "x",
label = "Select x variable:",
multiple = TRUE,
choices = NULL,
options = list(maxItems = 1)
),
selectizeInput(
inputId = "y",
label = "Select a y variable",
multiple = TRUE,
choices = NULL,
options = list(maxItems = 1)
)
),
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 = {
updateSelectizeInput(session,
"x",
choices = names(data()),
selected = NULL)
updateSelectizeInput(session,
"y",
choices = names(data()),
selected = NULL)
})
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))
how to read and update the values of 'selectInput'
1) In the data
reactive, you read the input field uploadedcsv
, but in the ui, it's called uploadcsv
(Note the missing ed
). If you make this consistent, the upload should work.
2) The observe
runs when the app starts; at that point data()
returns NULL
, so max(data()$Time
is max(NULL)
, which is -Inf
. You should wait until the data is loaded. One way to do this is to change observe
to observeEvent
:
observeEvent(data, { # and so on...
another option is to keep observe
and add req(data)
at the beginning of the observer.
Reactive select input to update table
Here is a quick prototype for your task
library(shiny)
library(tidyverse)
library(DT)
# 1. Dataset
df_demo <- data.frame(
age = c(16, 17, 18, 19, 20),
name = c("Peter", "Mary", "Mike", "Nick", "Phillipe"))
# 2. Server
server <- function(input, output, session) {
# 1. UI element 'Age'
output$ui_select_age <- renderUI({
selectInput("si_age", "Age", df_demo$age)
})
# 2. Reactive data set
df_data <- reactive({
# 1. Read UI element
age_selected <- input$si_age
# 2. Filter data
df <- df_demo %>%
filter(age == age_selected)
# 3. Return result
df
})
# 3. Datatable
output$dt_table <- renderDataTable({
datatable(df_data())
})
}
# 3. UI
ui <- fluidPage(
fluidRow(uiOutput("ui_select_age")),
fluidRow(dataTableOutput("dt_table"))
)
# 4. Run app
shinyApp(ui = ui, server = server)
Update on File Upload Shiny R
Hi don't pass variable to the global environnement, use shiny reactive feature instead, your server should be :
library(shiny)
library(ggplot2)
# Test data
# write.csv(x = iris, file = "iris.csv", row.names = FALSE)
# write.csv(x = data.frame(V1 = 1:10, V2 = rnorm(10)), file = "test.csv", row.names = FALSE)
shinyServer(function(input, output) {
tableData <- reactive({
inFile <- input$file1
if (!is.null(inFile)){
read.csv(inFile$datapath)
} else {
mtcars
}
})
#for x values
output$opt.x <- renderUI({
selectInput("xcolumn", "X column to Plot", names(tableData()))
})
output$your_data <- renderTable({
head(tableData())
})
})
And replace your main panel with :
mainPanel(
tableOutput("your_data")
)
I remove the params in read.csv
since those input are not defined in the UI.
EDIT
Try this app, it's not a shiny solution but a jquery/js one (the difference is in the ui) (see this answer) :
library("shiny")
ui <- fluidPage(
titlePanel("App"),
sidebarLayout(
sidebarPanel(
fileInput('file1', 'Choose CSV File',
accept = c('.csv','.tsv')
),
tags$script(
'$( "#file1" ).on( "click", function() {
this.value = null;
});'
),
uiOutput("opt.x")
),
mainPanel(
tableOutput("your_data")
)
)
)
server <- function(input, output) {
tableData <- reactive({
inFile <- input$file1
if (!is.null(inFile)){
read.csv(inFile$datapath)
} else {
mtcars
}
})
#for x values
output$opt.x <- renderUI({
selectInput("xcolumn", "X column to Plot", names(tableData()))
})
output$your_data <- renderTable({
head(tableData())
})
}
shinyApp(ui = ui, server = server)
For testing I used :
write.csv(x = data.frame(V1 = 1:10, V2 = rnorm(10)), file = "test.csv", row.names = FALSE)
write.csv(x = data.frame(V11 = 11:20, V12 = rnorm(10), ABC = letters[1:10]), file = "test.csv", row.names = FALSE)
Update dropdown values in R shiny dynamically
You need to return the content within your if statements. You can do this using return
library(shiny)
library(shinyWidgets)
# Define the UI
ui <- bootstrapPage(
column(3, uiOutput("class_level")),
column(3,uiOutput("product"))
)
# Define the server code
server <- function(input, output) {
output$class_level <- renderUI({
selectInput(
"selected_class",
label = h4("Classification Level"),
choices = list(
"Brand" = "Brand",
"Brand1" = "Brand1",
"Brand2" = "Brand2"
),
selected = "Brand"
)
})
getFlavor <- reactive({
if (input$selected_class =="Brand") {
return(c( "a " = "a",
"b" = "b",
"c" = "c"
))
}
else if (input$selected_class =="Brand1")
{
return(c(
"1" = "1",
"2" = "2",
"3" = "3"
))
}
else (input$selected_class =="Brand2")
{
return(
c(
"x" = "x",
"y" = "y",
"z" = "z"
))
}
})
output$product <- renderUI({
pickerInput(
"selected_product",
label = h4("Product Family"),
choices = as.list(getFlavor()),
selected = as.list(getFlavor()),
options = list(
`deselect-all-text` = "None",
`select-all-text` = "Total",
`actions-box` = TRUE
),
multiple = F,
width = "100%"
)
})
}
# Return a Shiny app object
shinyApp(ui = ui, server = server)
Related Topics
Show Correlations as an Ordered List, Not as a Large Matrix
R: What Are Operators Like %In% Called and How to Learn About Them
Merging More Than 2 Dataframes in R by Rownames
How to Install Roracle Package on Windows 7
Simple Examples of Filter Function, Recursive Option Specifically
Horizontal Dendrogram in R with Labels
Creating Multi Column Legend in Ggplot
No Visible Global Function Definition for 'Median'
Solving Simultaneous Equations with R
Row Sums Over Columns with a Certain Pattern in Their Name
Can You Specify Different Geoms for Different Facets in a Ggplot
Possible to Create Rd Help Files for Objects Not in a Package
Setting Work Directory in Knitr Using Opts_Chunk$Set(Root.Dir = ...) Doesn't Work
Replicate Each Row of Data.Frame and Specify the Number of Replications for Each Row