How can I implement the functionality in a Shiny App where there are two tabs, "Hex Map" and "State Information"?
In the "Hex Map" tab, there is a highchart displaying a hex map of the United States. On the "State Information" tab, there is a selectInput element that allows the user to choose a state and view information about that state.
What I would like to achieve is that when a user clicks on one of the states in the "Hex Map" tab, they should be automatically redirected to the "State Information" tab. Furthermore, I want the selectInput in the "State Information" tab to be pre-selected with the state that was clicked on in the "Hex Map" tab. For instance, if the user clicks on Alaska, the "State Information" tab should be displayed with Alaska selected in the selectInput dropdown.
Can you please provide guidance on how to implement this functionality using R and the Shiny package? I think I am close with the code below.
library(shiny)
library(highcharter)
library(usmap)
# Define state names vector
state_names <- state.name
# UI function
ui <- fluidPage(
# Tabset panel
tabsetPanel(
# Hex Map panel
tabPanel(
"Hex Map",
highchartOutput("hex_map", width = "100%", height = "500px")
),
# State Information panel
tabPanel(
"State Information",
selectInput("state_dropdown", "Select a State", choices = state_names),
verbatimTextOutput("state_info")
)
)
)
# Server function
server <- function(input, output, session) {
# Generate the hex map using Highcharts
output$hex_map <- renderHighchart({
state_df <- data.frame(state = state.name, abb = state.abb) # Create dataframe with state names and abbreviations
hcmap("countries/us/us-all", data = state_df, value = "abb") %>%
hc_title(text = "US Hex Map") %>%
hc_plotOptions(
series = list(
cursor = "pointer",
point = list(
events = list(
click = JS("function() {
var selected_state = this.abb;
Shiny.setInputValue('selected_state', selected_state, {priority: 'event'});
Shiny.setInputValue('tab_switched', 'state_info_tab', {priority: 'event'});
}")
)
)
)
)
})
# Update selectInput when a state is clicked
observeEvent(input$selected_state, {
selected_state <- input$selected_state
updateSelectInput(session, "state_dropdown", selected = selected_state)
})
# Automatically switch to "State Information" tab and select clicked state
observeEvent(input$tab_switched, {
if (input$tab_switched == "state_info_tab") {
selected_state <- input$selected_state
updateSelectInput(session, "state_dropdown", selected = selected_state)
}
}, ignoreInit = TRUE)
# Automatically switch to "State Information" tab when a state is selected
observeEvent(input$state_dropdown, {
selected_state <- input$state_dropdown
updateTabsetPanel(session, "tabsetPanel", selected = "State Information")
updateSelectInput(session, "selected_state", selected = selected_state)
})
# Render state information
output$state_info <- renderPrint({
state <- input$state_dropdown
get_state_info(state)
})
# Helper function to retrieve state information
get_state_info <- function(state) {
# Placeholder implementation, replace with your own logic
paste("State:", state)
}
}
# Run the app
shinyApp(ui, server)
2
Answers
So just a couple of changes. Firstly, the name of the selected state will be
this.name
notthis.abb
(you can add aconsole.log(this)
and check in console for which is the correct name). Secondly add an id fortabsetPanel
and in JS function you need to use the title of the tab to be selected. Finally add an observer to update tabs whenever tab is changed via JS. The updated code is below: