1

I am attempting to create two drop downs in shiny - one a list of states that then filters the second drop down which lists all counties for the selected state. The following code works BUT the counties do not update when you change states.

UI

pageWithSidebar(
 headerPanel("My chart"),
 sidebarPanel(
  uiOutput("sel_state"),
  uiOutput("sel_county")
 ),
 mainPanel(
  tableOutput("table")
 )
)

Server

function(input, output, session) {

  output$sel_state <- renderUI({
   selectizeInput('state', 'Select a State', choices=c("Choose One" = "", state_list))
  })

  output$sel_county <- renderUI({
   county_list <- reactive({
    df %>%
     filter(state == input$state) %>%
     pull(county) %>%
     sort() %>%
     as.character()
   })
    selectizeInput('county', 'Select a County', choices=c("Choose One" = "", county_list()))
  })

  tab <- reactive({
   df %>%
    filter(state == input$state) %>%
    filter(county == input$county)
  })

  output$table <- renderTable({
   tab()
  })
 }

I attempted to replace the 'selectizeInput' in the county drop down with the following 'updateSelectizeInput' but keep getting the following error

New Server line

updateSelectizeInput(session, 'county', 'Select a County', choices=c("Choose One" = "", county_list()))

ERROR: cannot coerce type 'environment' to vector of type 'character'

Code to create data frames - the county list is not a proper list yet

    x <- getURL("https://raw.githubusercontent.com/nytimes/covid-19-data/master/us-counties.csv")
    csv <- read.csv(text=x)
    df <- as.data.frame(csv)
    state_list <- c(levels(df$state))
    county_list <- subset(df, select = c(3,2))

dput output

dput(head(cl))
structure(list(state = c("Washington", "Washington", "Washington", 
"Illinois", "Washington", "California"), county = c("Snohomish", 
"Snohomish", "Snohomish", "Cook", "Snohomish", "Orange")), row.names = 
c(NA, 6L), class = "data.frame")
orBeFamous
  • 11
  • 2
  • Don't replace selectizeInput with updateSelectizeInput. Add it to the server. The selectizeInput makes an input with id = county and updateSelectizeInput can update the input that has an id = county. – bs93 Apr 07 '20 at 14:38
  • The getURL does not work for me. When I run url.exists() it returns 'FALSE'. Can you try to 'dput(df)' and copy/paste the output into the question too? As described in this answer: https://stackoverflow.com/a/49995752/11437205 – bs93 Apr 07 '20 at 15:52
  • Done! I just pulled using head() since it's a big set of data I also fixed the URL, it just was formatted oddly in the question, you should be able to reuse that now if you'd prefer. – orBeFamous Apr 07 '20 at 16:13
  • Thanks - updated answer. – bs93 Apr 07 '20 at 16:22

1 Answers1

0

I don't have your state/county info (or its structure), but this small example accomplishes what I think you describe. Things to note:

You need to first make the select input UI element with selectizeInput and then you can update its contents with updateSelectizeInput. So you need both functions, but for this small reprex I created the updateSelectizeInput is not needed though so I may have mis-interpreted what you are wanting to do.

In this example the county selectInput is receiving a reactive object as its choices input based on subsetting the county list by the user state selection, so the county select input will update as the user switches between states.

I also wrapped the county input with a conditionalPanel - this input will only show if the user has selected a state with the state selectInput.

UPDATE* add 'req(length(input$state) > 0)' so the reactive does not execute in server until state selected

library(shiny)
library(tidyverse)

ui <- fluidPage(


    pageWithSidebar(
        headerPanel("My chart"),
        sidebarPanel(
            uiOutput("sel_state"),
            conditionalPanel(condition = "input.state.length > 0",

            uiOutput("sel_county")
            )
        ),
        mainPanel(

        )
    )
)


server <- function(input, output) {

    #create example of data structure
   df <- structure(list(state = c("Washington", "Washington", "Washington", 
                         "Illinois", "Washington", "California"), county = c("Snohomish", 
                                                                             "Snohomish", "Snohomish", "Cook", "Snohomish", "Orange")), row.names = 
              c(NA, 6L), class = "data.frame")
   #pull out unique state names
    state_list <- as.character(unique(df$state))

    #filter for counties only in desired state and pull column to vector 
    selected_state_counties <- reactive({
    req(length(input$state) > 0)
        df %>% 
            filter(state == input$state) %>% 
            pull(county) %>% 
            as.character()

    })

output$sel_state <- renderUI({
        selectizeInput('state', 'Select a State', choices=c("Choose One" = "", state_list))
    })

output$sel_county <- renderUI({
        selectizeInput('county', 'Select a County', choices=c("Choose One" = "", selected_state_counties()))
    })


}

# Run the application 
shinyApp(ui = ui, server = server)
bs93
  • 1,236
  • 6
  • 10
  • This is great! The only thing I'm running into is the data structure - as you said. I've got the states and counties in one dataframe so making the state_list is easy but I'm trying to turn my two column data frame into a county_list like you have. My data frame is currently a column of states then a column of counties (so there are states listed multiple times) – orBeFamous Apr 07 '20 at 15:25
  • If you are able to add a small example of your data structure I will try to rework a solution. If a reference is needed for doing so: https://stackoverflow.com/help/minimal-reproducible-example – bs93 Apr 07 '20 at 15:33
  • I added my code to pull my data to my original question because I'm dumb and can't figure out how to properly format a comment :) – orBeFamous Apr 07 '20 at 15:37
  • Just updated answer based on your first comment here – bs93 Apr 07 '20 at 16:20
  • Also, add in 'req(length(input$state) > 0)' into the selected_state_counties reactive. I noticed a small warning being thrown in R console. I, again, updated the answer. – bs93 Apr 07 '20 at 16:28
  • I've gotten my app to work but now get an unrelated error, if you're intersted: https://stackoverflow.com/questions/61085538/error-replacement-has-1-row-data-has-0-in-r-shiny-app – orBeFamous Apr 07 '20 at 17:10