Rshiny selectInput -- figure out the name of the list where user make the selection

The title may be confusing but a simple example would make the problem obvious.

In the code below, both 'East Coast' and 'West Coast' have the entry "NY". If the user selects "NY", is there a way for the server side to know if the user actually selects it from 'East Coast' or 'West Coast' ? Is this possible?

shinyApp(
  ui = fluidPage(
    selectInput("state", "Choose a state:",
      list(`East Coast` = c("NY", "NJ", "CT"),
           `West Coast` = c("NY", "OR", "CA"),
           `Midwest` = c("MN", "WI", "IA"))
    ),
    textOutput("result")
  ),
  server = function(input, output) {
    output$result <- renderText({
      paste("You chose", input$state)
    })
  }
)
}```

Yes, by providing named vectors for the elements of the list. The code can be optimized of course, but I hope it illustrates the idea.

library(shiny)
library(tidyverse)

state_lst <-list(
    `East Coast` = c("NY" = "NY1", "NJ" = "NJ", "CT" = "CT"),
    `West Coast` = c("NY" = "NY2", "OR" = "OR", "CA" = "CA"),
    `Midwest` = c("MN" = "MN", "WI" = "WI", "IA" = "IA"))

shinyApp(
    ui = fluidPage(
        selectInput("state", "Choose a state:", state_lst),
        textOutput("result")
    ),
    server = function(input, output) {
        output$result <- renderText({
            region <- 
                state_lst %>% 
                purrr::keep(~ input$state %in% .x) %>% 
                names()
            state <- 
                state_lst %>% 
                purrr::flatten_chr() %>%
                purrr::keep(~ input$state %in% .x) %>% 
                names()
            paste("You chose", region, "&", state, "from input:", input$state)
        })
    }
)
2 Likes

It seems purrr is the most convenient way to do it, am I right?

If I change both NY1 to NY2 to NY, i.e. not differentiate them explicitly, the program seems to behave differently. Is there a way to fix that?

library(shiny)
library(tidyverse)

state_lst <-list(
    `East Coast` = c("NY" = "NY", "NJ" = "NJ", "CT" = "CT"),
    `West Coast` = c("NY" = "NY", "OR" = "OR", "CA" = "CA"),
    `Midwest` = c("MN" = "MN", "WI" = "WI", "IA" = "IA"))

shinyApp(
    ui = fluidPage(
        selectInput("state", "Choose a state:", state_lst),
        textOutput("result")
    ),
    server = function(input, output) {
        output$result <- renderText({
            region <- 
                state_lst %>% 
                purrr::keep(~ input$state %in% .x) %>% 
                names()
            state <- 
                state_lst %>% 
                purrr::flatten_chr() %>%
                purrr::keep(~ input$state %in% .x) %>% 
                names()
            paste("You chose", region, "&", state, "from input:", input$state)
        })
    }

There might be some solution out there that involves javascript or digging deeper into shiny and that I do not know about. Here the trick is to differentiate between the elements of the list.

Shiny displays the name but returns only the value, thus the quick way to distinguish between the two NY's is to give them different values (can be NY1, NY2 or just 1, 2, etc.) and the same name (NY) do display. If you give them the same values (as in your modified example), the example will work.

2 Likes