Shiny doesn't show me the entire selectInput when I have choices 1000
Use selectizeInput
instead of selectInput
with the argument options = list(maxOptions = 3000)
.
selectInput not showing the choices and resetting values to 'All' in shinyApp
I've done several modifications in your code. In particular, I've added some req
's (see ?req
), and in output$disp_selector
I've modified available
:
available <- data_table[["disp"]][data_table$vs %in% input$vs]
if(! "All" %in% input$carb){
available <- available[data_table$carb %in% input$carb]
}
data_table<-mtcars
#ui
ui = fluidPage(
sidebarLayout(
sidebarPanel (
uiOutput("vs_selector"),
uiOutput("carb_selector"),
uiOutput("disp_selector")),
mainPanel(
DT::dataTableOutput('mytable')
)
))
#server
server = function(input, output, session) {
output$vs_selector <- renderUI({
selectInput(inputId = "vs",
label = "vs:", multiple = TRUE,
choices = c( unique(data_table$vs)),
selected = c(0,1))
})
output$carb_selector <- renderUI({
req(input$vs)
available0 <- data_table[c(data_table$vs %in% input$vs ), "carb"]
selectInput(
inputId = "carb",
label = "carb:",
multiple = TRUE,
choices = c('All',as.character(unique(available0))),
selected = 'All')
})
output$disp_selector <- renderUI({
req(input$vs, input$carb)
available <- data_table[["disp"]][data_table$vs %in% input$vs]
if(! "All" %in% input$carb){
available <- available[data_table$carb %in% input$carb]
}
selectInput(
inputId = "disp",
label = "disp:",
multiple = TRUE,
choices = c('All',as.character(unique(available))),
selected = 'All')
})
thedata <- reactive({
req(input$disp, input$vs, input$carb)
data_table<-data_table[data_table$vs %in% input$vs,]
if(! "All" %in% input$carb){
data_table<-data_table[data_table$carb %in% input$carb,]
}
if(! "All" %in% input$disp){
data_table<-data_table[data_table$disp %in% input$disp,]
}
data_table
})
output$mytable = DT::renderDataTable({
DT::datatable( {
thedata() # Call reactive thedata()
})
})
}
shinyApp(ui = ui, server = server)
FYI, for a cleaner solution, you might be interested in selectizeGroupUI
in the shinyWidgets
package:
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
fluidRow(
column(
width = 10, offset = 1,
tags$h3("Filter data with selectize group"),
panel(
selectizeGroupUI(
id = "my-filters",
params = list(
disp = list(inputId = "disp", title = "disp:"),
carb = list(inputId = "carb", title = "carb:"),
vs = list(inputId = "vs", title = "vs:")
)
), status = "primary"
),
dataTableOutput(outputId = "table")
)
)
)
server <- function(input, output, session) {
res_mod <- callModule(
module = selectizeGroupServer,
id = "my-filters",
data = mtcars,
vars = c("disp", "carb", "vs")
)
output$table <- renderDataTable(res_mod())
}
shinyApp(ui, server)
How to make selectInput choices reactive?
You should avoid renderUI
where possible and use update*
functions instead - updating is faster than re-rendering:
library(shiny)
library(data.table)
DT <- data.table(
ID = c(1, 1, 1, 2, 2, 2, 3, 3, 3),
Period = c(1, 2, 3, 1, 2, 3, 1, 2, 3),
Values = c(5, 10, 15, 0, 2, 4, 3, 6, 9)
)
all_choices <- unique(DT$Period)
ui <- fluidPage(
tableOutput("data"),
selectizeInput(
inputId = "fromPeriod",
label = "From period:",
choices = setdiff(all_choices, last(all_choices)),
selected = 1
),
selectizeInput(
inputId = "toPeriod",
label = "To period:",
choices = setdiff(all_choices, first(all_choices)),
selected = 2
),
tableOutput("dataSelect")
)
server <- function(input, output, session) {
output$data <- renderTable({
DT
})
observeEvent(input$fromPeriod, {
freezeReactiveValue(input, "toPeriod")
updateSelectizeInput(
session,
inputId = "toPeriod",
choices = all_choices[all_choices > input$fromPeriod],
selected = max(all_choices[all_choices > input$fromPeriod])
)
}, ignoreInit = TRUE)
output$dataSelect <- renderTable({
# in one line, however you seem to need part1 / part2 for your custom function
# setorder(DT[Period %in% c(input$fromPeriod, input$toPeriod)], Period)
part1 <- DT[Period == input$fromPeriod]
part2 <- DT[Period == input$toPeriod]
rbindlist(list(part1, part2))
}, rownames = TRUE)
}
shinyApp(ui, server)
To avoid triggering reactives or outputs unnecessarily you should almost alway use freezeReactiveValue
when using a update*
function in shiny. Please see this related chapter from Mastering Shiny.
Updating selection of server-side selectize input with 1000 choices fails
The short answer is explicitly re-specify your choices
and server
in your update.
server <- function(input, output, session)
{
myChoices <- paste("Item", 1:10000)
updateSelectizeInput(session, "listid", choices = myChoices, server = T)
observeEvent(input$buttonid,
{
updateSelectizeInput(session, "listid",
server = TRUE,
choices = myChoices,
selected = "Item 1234")
})
}
The default for server
in updateSelectizeInput
is FALSE
. This causes the code to drop into a control statement which uses updateSelectInput
instead. From the function code
function (session, inputId, label = NULL, choices = NULL, selected = NULL,
options = list(), server = FALSE)
{
...
if (!server) {
return(updateSelectInput(session, inputId, label, choices,
selected))
}
...
This sends a message to the client assuming all the choices are present (but as you mentioned, only the first 1000 are present).
Just setting server = TRUE
results in an error when you click the button.
Warning: Error in [.data.frame: undefined columns selected
[No stack trace available]
I didn't fully trace the reason, but it ultimately creates an empty choices data.frame with an attribute denoting the selected value. I'm guessing somewhere else in function calls to the session
object, this attribute is being used to try to select a column created from the empty data.frame.
The update function doesn't seem to change the choices
stored on the server, so that's presumably why it's there when you search for it. During the changing the selected value, it seems to be trying to select from a NULL list of choices instead of the list of choices on the server.
It seems like you essentially have to recreate your selectizeInput
when updating with a selected value beyond your initial list.
The ability to select ALL potential options in a Shiny input along with a dynamic table
Here is something to try out. You can use updateSelectInput
to change your inputs and make them dependent. A separate reactive
expression can filter your data based on your inputs. See if this gives you the intended behavior.
library(shiny)
library(DT)
State <- c("NV", "NV","NV", "MD", "MD", "MD", "MD", "NY", "NY", "NY", "OH", "OH", "OH")
County <- c("CLARK", "WASHOE", "EUREKA", "MONTGOMERY", "HOWARD", "BALTIMORE", "FREDERICK", "BRONX", "QUEENS", "WESTCHESTER", "FRANKLIN", "SUMMIT", "STARK" )
City <- c("Las Vegas", "Reno", "Eureka", "Rockville", "Columbia", "Baltimore", "Thurmont", "Bronx", "Queens", "Yonkers", "Columbus", "Akron", "Canton")
Rating<- c(1,2,3,4,5,6,7,8,9,10,11,12,13)
df <- data.frame(State, County, City, Rating, stringsAsFactors = F)
ui <- fluidPage(
titlePanel("Test Dashboard "),
sidebarLayout(
sidebarPanel(
selectInput("data1", "Select State", choices = c("All", unique(df$State))),
selectInput("data2", "Select County", choices = NULL),
selectInput("data3", "select City", choices = NULL)
),
mainPanel(
DTOutput("table")
)
))
server <- function(input, output, session){
observeEvent(input$data1, {
if (input$data1 != "All") {
updateSelectInput(session, "data2", "Select County", choices = c("All", unique(df$County[df$State == input$data1])))
} else {
updateSelectInput(session, "data2", "Select County", choices = c("All", unique(df$County)))
}
}, priority = 2)
observeEvent(c(input$data1, input$data2), {
if (input$data2 != "All") {
updateSelectInput(session, "data3", "Select City", choices = c("All", unique(df$City[df$County == input$data2])))
} else {
if (input$data1 != "All") {
updateSelectInput(session, "data3", "Select City", choices = c("All", unique(df$City[df$State == input$data1])))
} else {
updateSelectInput(session, "data3", "Select City", choices = c("All", unique(df$City)))
}
}
}, priority = 1)
filtered_data <- reactive({
temp_data <- df
if (input$data1 != "All") {
temp_data <- temp_data[temp_data$State == input$data1, ]
}
if (input$data2 != "All") {
temp_data <- temp_data[temp_data$County == input$data2, ]
}
if (input$data3 != "All") {
temp_data <- temp_data[temp_data$City == input$data3, ]
}
temp_data
})
output$table <- renderDT(
filtered_data()
)
}
shinyApp(ui, server)
R shiny passing reactive to selectInput choices
You need to use renderUI
on the server side for dynamic UIs. Here is a minimal example. Note that the second drop-down menu is reactive and adjusts to the dataset you choose in the first one. The code should be self-explanatory if you have dealt with shiny before.
runApp(list(
ui = bootstrapPage(
selectInput('dataset', 'Choose Dataset', c('mtcars', 'iris')),
uiOutput('columns')
),
server = function(input, output){
output$columns = renderUI({
mydata = get(input$dataset)
selectInput('columns2', 'Columns', names(mydata))
})
}
))
EDIT. Another Solution using updateSelectInput
runApp(list(
ui = bootstrapPage(
selectInput('dataset', 'Choose Dataset', c('mtcars', 'iris')),
selectInput('columns', 'Columns', "")
),
server = function(input, output, session){
outVar = reactive({
mydata = get(input$dataset)
names(mydata)
})
observe({
updateSelectInput(session, "columns",
choices = outVar()
)})
}
))
EDIT2: Modified Example using parse
. In this app, the text formula entered is used to dynamically populate the dropdown menu below with the list of variables.
library(shiny)
runApp(list(
ui = bootstrapPage(
textInput("text", "Enter Formula", "a=b+c"),
uiOutput('variables')
),
server = function(input, output){
outVar <- reactive({
vars <- all.vars(parse(text = input$text))
vars <- as.list(vars)
return(vars)
})
output$variables = renderUI({
selectInput('variables2', 'Variables', outVar())
})
}
))
Multiple reactive selectinput based on another in R shiny
Set choices to NULL within renderUI and update it via updateSelectInput while keeping the current selection:
output$sources <- renderUI({
selectInput(
inputId = "SOURCE",
"Select source",
choices = NULL,
multiple = T
)
})
observeEvent(var_source(),{
updateSelectInput(
inputId = "SOURCE",
choices = var_source(),
selected = input$SOURCE
)
})
shiny::selectInput(): Unable to remove an element/variable based on index
Is this what you want?
library(shiny)
data <- c("cultivar","control", "stress")
ui <- fluidPage(
selectInput("select1", "Select variable", choices = data),
uiOutput("UiSelect2")
)
server <- function(input, output, session) {
output$UiSelect2 <- renderUI({
#remove the selected element based on index
newData <- data[!data %in%input$select1]
selectInput("select2","Select another variable", choices = newData)
})
}
shinyApp(ui, server)
Related Topics
How to Get Rows, by Group, of Data Frame with Earliest Timestamp
Relationship Between R Markdown, Knitr, Pandoc, and Bookdown
R Sequence of Dates with Lubridate
Change the Color of Action Button in Shiny
How to Syntax Highlight Inline R Code in R Markdown
Sliding Time Intervals for Time Series Data in R
Side by Side Histograms in the Same Graph in R
How to Extract Everything Until First Occurrence of Pattern
Separate Columns with Constant Numbers and Condense Them to One Row in R Data.Frame
How to Organize Large Shiny Apps
To Find Whether a Column Exists in Data Frame or Not
Adding Custom Image to Geom_Polygon Fill in Ggplot
How to Check If a Sequence of Numbers Is Monotonically Increasing (Or Decreasing)
How to Get Currency Exchange Rates in R
R: Unexpected Results from P.Adjust (Fdr)
Building a Box Plot from All Columns of Data Frame with Column Names on X in Ggplot2