In my app, I can select car names, and this first selection updates two additional inputs: the category of the car (A or B) and the range of mpg. I can do it so far, but I have some trouble when I try to make those two additional inputs dependent on each other. The reason I want to make these dependent on each other is that these two inputs are not "ordered", meaning that one input is not more important than the other.
In the example below, I selected 4 cars, some being in A category and others in B category. When I select only category B, the range is updated so that it corresponds to the cars in the category that I selected.
This works in this order (changing the first input updates the range), but I can't figure out how to make these two inputs dependent on each other. For example, when I reduce the mpg range to 20-21, the only category left in the table is A, so the first input should only show A. Adding another observeEvent() after the definition of third_data() makes both inputs empty.
library(shiny)
library(dplyr)
library(tibble)
mtcars$category <- rep(c("A", "B"), each = 16)
mtcars2 <- mtcars %>%
rownames_to_column("car_name")
ui <- fluidPage(
selectInput("car_name", "car name", unique(mtcars2$car_name),
multiple = TRUE, selected = c("Mazda RX4", "Dodge Challenger",
"AMC Javelin", "Camaro Z28")),
selectInput("category", "category", NULL, multiple = TRUE),
sliderInput("range_mpg", "range of mpg",
min = 0,
max = 0,
value = c(0, 0)),
tableOutput("test_table")
)
server <- function(input, output, session) {
first_data <- reactive({
mtcars2 %>%
filter(car_name %in% input$car_name)
})
observeEvent(first_data(), {
updateSelectInput(
session = session,
inputId = "category",
choices = unique(first_data()$category),
selected = unique(first_data()$category)
)
updateSliderInput(
session = session,
inputId = "range_mpg",
min = min(first_data()$mpg),
max = max(first_data()$mpg),
value = c(min(first_data()$mpg), max(first_data()$mpg))
)
})
second_data <- reactive({
first_data() %>%
filter(category %in% input$category)
})
observeEvent(second_data(), {
updateSliderInput(
session = session,
inputId = "range_mpg",
min = min(second_data()$mpg),
max = max(second_data()$mpg),
value = c(min(second_data()$mpg), max(second_data()$mpg))
)
})
third_data <- reactive({
second_data() %>%
filter(between(mpg, input$range_mpg[1], input$range_mpg[2]))
})
output$test_table <- renderTable({
third_data()
})
}
shinyApp(ui, server)
To summarize, here's the expected behavior:
- when I select the first input, the range should be updated to correspond to the cars in the category selected in the first input (DONE).
- when I change the range, the first input should be updated, so that it displays categories of cars that are in this range.
Any idea on how to do this, or on another "app workflow"?