R shiny: switchInput to control order of reactive filters

111 Views Asked by At

I'm looking to create a shiny dashboard that includes a switchInput, 3 selectInput/pickerInputs, and a data table that reacts to all the filters. I want the switchInput to control the order of the first 2 select/pickerinputs, and the third pickerInput will always have the same position.

When the switch is TRUE, I want the first filter to determine the number of cylinders (cyl), the second filter to reactively change choices for number of gears (gear) based on the cyl choice, and the third filter to reactively change choices for transmission (am) based on the previous two choices. The data table then should reflect the filtering choices.

When the switch is FALSE, I want the first filter to determine the number of gears (gear), the second filter to reactively change choices for number of cylinders (cyl) based on the gear choice, and the third filter to reactively change choices for transmission (am) based on the previous two choices. The data table then should reflect the filtering choices.

Right now, when I filter with the switch on TRUE, the table reflects my filters and changes interactively, but when I use the switch back and forth, the filters will retain the choices that were set before flipping the switch.

I would like the filters and data table to reset each time I flip the switch and not hold over any information from choices made pre-switch.

My reprex is below, please let me know if you need any more information.

library(MASS)
library(shiny)
library(dplyr)
library(shinydashboard)
library(DT)
library(shinyWidgets)

mtcars <- mtcars

ui <- basicPage(
  h4("Cars data"),
  fluidRow(
    column(width = 2, switchInput("switch1", label = NULL, value = TRUE, onLabel = "Cylinders First", offLabel = "Gears First", handleWidth = '25px')),
    column(width = 2, uiOutput("filter1")),
    column(width = 2, uiOutput("filter2")),
    column(width = 2, uiOutput("filter3"))
  ),
  br(),
  DT::dataTableOutput("my_table"),
  br()
)

server <- function(input, output, session) {
  
  #mtcars <- reactive({mtcars})
  
  output$filter1 <- renderUI({
    if (input$`switch1` == T) { #cylinder filter
      cyl_choice1 <- sort(unique(mtcars$cyl))
      selectInput("cyl_num", "Select Number of Cylinders", cyl_choice1, multiple = F)
    } else { #gear filter
      gear_choice1 <- sort(unique(mtcars$gear))
      selectInput("gear_num", "Select Number of Gears", gear_choice1, multiple = F)
    }
  })
  
  output$filter2 <- renderUI({
    if (input$`switch1` == T) { #gear filter
     if (!length(input$`cyl_num`)) return();
      mtcars <- mtcars %>% dplyr::filter(`cyl` == as.numeric(input$`cyl_num`))
      gear_choice2 <- sort(unique(mtcars$gear))
      pickerInput("gear_num", "Select Number of Gears", gear_choice2, multiple = T, options = list(`actions-box` = T), selected = gear_choice2)
    } else { #cylinder filter
     if (!length(input$`gear_num`)) return();
      mtcars <- mtcars %>% dplyr::filter(`gear` == as.numeric(input$`gear_num`))
      cyl_choice2 <- sort(unique(mtcars$cyl))
      pickerInput("cyl_num", "Select Number of Cylinders", cyl_choice2, multiple = T, options = list(`actions-box` = T), selected = cyl_choice2)
    }
  })
  
  output$filter3 <- renderUI({
    mtcars <- mtcars %>% dplyr::filter(`cyl` %in% input$`cyl_num`)
    mtcars <- mtcars %>% dplyr::filter(`gear` %in% input$`gear_num`)
    am_choice <- sort(unique(mtcars$am))
    pickerInput("am_choice", "Select A (0) or M (1)", am_choice, multiple = T, options = list(`actions-box` = T), selected = am_choice)
  })
  
  output$my_table <- renderDataTable({
    mtcars <- mtcars %>% dplyr::filter(`cyl` %in% input$`cyl_num`)
    mtcars <- mtcars %>% dplyr::filter(`gear` %in% input$`gear_num`)
    mtcars <- mtcars %>% dplyr::filter(`am` %in% input$`am_choice`)
    DT::datatable(mtcars, options = list(pageLength = 30))
  })
  

}

# Create Shiny object
shinyApp(ui = ui, server = server)

Right now I have the input names as the same thing (regardless of switch == T or switch == F), but the names of choice-lists are different. I have tried having the names of choice-lists be the same (after necessary filtering and regardless of switch == T or switch == F).

EDIT: I have added in the if(!length(input$...)) return(); within each if statement inside filter2

0

There are 0 best solutions below