9

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")
    )
  })
Gary
  • 2,137
  • 3
  • 23
  • 41

1 Answers1

12

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"))

})
nrussell
  • 18,382
  • 4
  • 47
  • 60
  • nrussell, I have one more question, actually. At the top of my Shiny app, I have a counter that displays the total number of Candy bars in the data set. How can I have this counter automatically update based on the subsequent filtering? I placed my current code in a revision. – Gary Oct 12 '15 at 18:51
  • @Nick Updated - and for future reference, you should ask a *separate* question, even if it is related to the original problem, so that the information is more easily searchable by other users of this site. – nrussell Oct 12 '15 at 19:07
  • thanks for the feedback and the update. Your help is very very much appreciated! – Gary Oct 12 '15 at 19:13
  • If I wanted to add a third level of filtering, what would the `available2` be? available2 <- candyData[candyData$Candy== input$Candy, "price"] was my first guess, but it is not correct. – Gary Oct 12 '15 at 20:38
  • Can you also explain how the `available` object works? I am confused with the brackets and the comma. – Gary Oct 13 '15 at 16:53
  • `available <- candyData[candyData$Brand == input$brand, ]`: `available` is the subset of `candyData` where `Brand` is equal to brand selected in `brand_selector`. – nrussell Oct 13 '15 at 16:58
  • And one final question, nrussell. I want to add a third layer of filtering, say, by Price, for my third `valueBox`. I want to create a subset that contains the Price for the given Candy bar. I am trying to create this subset by subtracting everything in the Price column except for the Prices for the chosen Candy bar. Do you know how I could do this? – Gary Oct 13 '15 at 17:25
  • 1
    As I noted in my first comment, you need to ask **a new question** instead of tacking on subquestions to your original problem. – nrussell Oct 13 '15 at 17:31
  • I've included it here: http://stackoverflow.com/questions/33109328/creating-a-third-valuebox-count-based-on-another-subset – Gary Oct 13 '15 at 17:49
  • I have a similar setup to this question, it is not enough to ask a new question though. How would you alter this to first display all choices in both menus but as soon as the user picks an option from 1 menu or the other it would update the list to reflect it? Basically how do I change this so the order of the menus does not matter? – Bear Jul 31 '18 at 14:57