rshiny

Filter one selectInput based on selection from another selectInput?


I have two selectInputs, and I would like the selection in the first one (Brand) to change the possible selections in the second one (Candy). So, for example, if someone chose "Nestle" in the first input box, then only Nestle candy bars will show up in the second box. My data table has a column for Brand and a column for Candy bar type.

I have the following code to start, but this shows ALL of the choices, regardless of the selection.

selectInput(inputId="brand", 
                  label="Brand:",
                  choices=as.character
                  (unique(candyData$Brand)),
                  selected = "Nestle"
    ),
    selectInput(inputId="candy", 
                label="Candy:",
                choices=as.character
                (unique(candyData$Candy)),
                selected = "100Grand"

The dataset looks like the following:

Brand       Candy
Nestle      100Grand
Netle       Butterfinger
Nestle      Crunch
Hershey's   KitKat
Hershey's   Reeses
Hershey's   Mounds
Mars        Snickers
Mars        Twix
Mars        M&Ms

Updated Question How do I update the ValueBox in my Dashboard based on the subsequent filtering?

output$count <- renderValueBox({

    valueBox(
      value = nrow(candyData),
      subtitle = "Number of Candy Bars",
      icon = icon("table")
    )
  })

Solution

  • Here's one approach:

    library(shiny)
    library(shinydashboard)
    ##
    ui <- shinyUI({
      sidebarPanel(
    
        htmlOutput("brand_selector"),
        htmlOutput("candy_selector"))
    
    })
    ##
    server <- shinyServer(function(input, output) {
      candyData <- read.table(
        text = "Brand       Candy
        Nestle      100Grand
        Netle       Butterfinger
        Nestle      Crunch
        Hershey's   KitKat
        Hershey's   Reeses
        Hershey's   Mounds
        Mars        Snickers
        Mars        Twix
        Mars        M&Ms",
        header = TRUE,
        stringsAsFactors = FALSE)
    
      output$brand_selector <- renderUI({
    
        selectInput(
          inputId = "brand", 
          label = "Brand:",
          choices = as.character(unique(candyData$Brand)),
          selected = "Nestle")
    
      })
    
      output$candy_selector <- renderUI({
    
        available <- candyData[candyData$Brand == input$brand, "Candy"]
    
        selectInput(
          inputId = "candy", 
          label = "Candy:",
          choices = unique(available),
          selected = unique(available)[1])
    
      })
    
    })
    ##
    shinyApp(ui = ui, server = server)
    

    Updated:

    You can modify the ui definition to be

    ui <- shinyUI({
      sidebarPanel(
    
        htmlOutput("brand_selector"),
        htmlOutput("candy_selector"),
        valueBoxOutput("count"))
    
    })
    

    and add the following to server:

    output$count <- renderValueBox({
    
      available <- candyData[candyData$Brand == input$brand, ]
    
      valueBox(
        value = nrow(available),
        subtitle = sprintf("Number of %s Candy Bars", input$brand),
        icon = icon("table"))
    
    })