I am attempting to dynamically update filters in my shiny app. For example, if one selects California as a state then the only cities that populate in the City filter should be cities from California.
However, if I select California, the code shows all the cities in the dataframe regardless if they are in California or not.
I have tried various attempts but am unsure of how to update the filtered data without creating a continuous loop or selecting a filter and it resetting itself. The original data has roughly twelve columns I am looking to filter.
library(shiny)
library(data.table)
library(DT)
ui <-
fluidPage(
# Application title
titlePanel("Display CSV Data"),
# Sidebar layout with input and output definitions
sidebarLayout(
# Sidebar panel for inputs
sidebarPanel(
# No input needed if the CSV is static
# Use selectizeInput for filtering
uiOutput("filter_ui")
),
# Main panel for displaying output
mainPanel(
# Output: DataTable
dataTableOutput("table")
)
)
)
server <-
function(input, output, session) {
# Read the CSV file into a data table and display as a DataTable
cols_to_filter <- c('state', 'city', 'county')
data <- reactive({
data.table(
state = c("California", "California", "California", "New York", "New York", "Texas", "Texas", "Texas"),
city = c("Los Angeles", "San Francisco", "Claremont", "New York", "Buffalo", "Houston", "Austin", "San Marcos"),
county = c("Los Angeles", "San Francisco", "Los Angeles", "New York", "Erie", "Harris", "Travis", "Hays"),
population = c(3979576, 883305, 36161, 8336817, 256902, 2325502, 964254, 65053) # Fictional population figures
)
})
observe({
setkeyv(data(), cols_to_filter)
})
# Generate selectizeInput for filtering
output$filter_ui <- renderUI({
filter_inputs <- lapply(cols_to_filter, function(col) {
selectizeInput(
inputId = paste0("filter_", col),
label = col,
choices = c("", sort(unique(data()[[col]]))),
multiple = TRUE,
options = list(
placeholder = 'Select values'
)
)
})
do.call(tagList, filter_inputs)
})
# Filter the data table based on user selections
filtered_data <- reactive({
filtered <- data()
for (col in cols_to_filter) {
filter_values <- input[[paste0("filter_", col)]]
if (length(filter_values) > 0) {
filtered <- filtered[get(col) %in% filter_values]
}
}
filtered
})
# Display the filtered data table
output$table <- renderDataTable({
filtered_data()
})
}
shinyApp(ui = ui, server = server)
You need to run
updateSelectizeInputif one of theSelectizeInputreceives a selection. Therefore you could include the code below: The firstlapplyattaches anobserveEventto allSelectizeInputand thelapplyinside contains the updates.