A common scenario for many of my shiny apps is that there is a large list of potentially interesting filter variables (often 10 to 20), but I want to avoid confusing the user with too many input widgets.
Therefore, my strategy is usually as follows: 1. Users may select filter variables. 2. If at least one filter variable is selected, a renderUI is triggered, which contains one input widget per selected variable. 3. The filter criteria are applied to the data and some output is generated.
The problem is that any change in step one (by adding or deleting a filter variable) eliminates all previously made choices from step two. This means that all input widgets are unintentionally reset to their default values. This prevents a smooth user experience. Any idea how to improve on this?
Here you can see what happens:
And here is the code to reproduce this behaviour:
library("shiny")
library("dplyr")
library("nycflights13")
df <- flights
filtervarsChoices <- c("origin","carrier")
originChoices <- unique(df$origin)
carrierChoices <- unique(df$carrier)
ui <- fluidPage(
h3("1. Select Filter variables"),
selectInput("filterVars", "Filter variables", filtervarsChoices, multiple = TRUE),
uiOutput("filterConditions"),
h3("Result"),
tableOutput("average")
)
server <- function(input, output, session) {
output$filterConditions <- renderUI({
req(input$filterVars)
tagList(
h3("2. Select Filter values"),
if ("origin" %in% input$filterVars) {
selectInput("originFilter", "Origin", originChoices, multiple = TRUE)
},
if ("carrier" %in% input$filterVars) {
selectInput("carrierFilter", "Carrier", carrierChoices, multiple = TRUE)
}
)
})
output$average <- renderTable({
if ("origin" %in% input$filterVars) {
df <- df %>% filter(origin %in% input$originFilter)
}
if ("carrier" %in% input$filterVars) {
df <- df %>% filter(carrier %in% input$carrierFilter)
}
df %>%
summarise(
"Number of flights" = n(),
"Average delay" = mean(arr_delay, na.rm = TRUE)
)
})
}
shinyApp(ui = ui, server = server)