I am working on an App where the user needs to walk through many, many choices to get to where he/she wants to go with data analysis. The App needs to easily "funnel" the user through the myriad choices without confusing the user, without leading the user into dead ends, etc. For example, funneling a user from general to more specific choices:
The image below shows the overall "funneling" structure I am thinking of using tabs/sidebar/main panel. In Shiny are there other efficient and clear ways to funnel a user through many choices?
Reproducible code for the skeleton structure shown in the image:
library(shiny)
library(shinyjs)
ui <-
pageWithSidebar(
headerPanel("Test"),
sidebarPanel(
useShinyjs(),
fluidRow(helpText(h5(strong("Base Input Panel")),align="center")),
conditionalPanel(
condition="input.tabselected==1",
h5("Selections for Tab 1:")
),
conditionalPanel(
condition="input.tabselected==2",
h5("Selections for Tab 2:")
)
), # close sidebar panel
mainPanel(
useShinyjs(),
tabsetPanel(
tabPanel("Tab 1", value=1,helpText("Tab 1 outputs")),
conditionalPanel(condition = "input.tabselected==1",
fluidRow(helpText("Tab 1 things happen here")),
),
tabPanel("Tab 2", value=2,
fluidRow(
radioButtons(
inputId = 'mainPanelBtnTab2',
label = h5(strong(helpText("Functions to access:"))),
choices = c('Function 1','Function 2','Function 3'),
selected = 'Function 1',
inline = TRUE
) # close radio buttons
), # close fluid row
conditionalPanel(condition = "input.tabselected==2",
fluidRow(helpText("Tab 2 things happen here")),
conditionalPanel(condition = "input.mainPanelBtnTab2 == 'Function 1'",
helpText("You pressed radio button 1")),
conditionalPanel(condition = "input.mainPanelBtnTab2 == 'Function 2'",
helpText("You pressed radio button 2")),
conditionalPanel(condition = "input.mainPanelBtnTab2 == 'Function 3'",
helpText("You pressed radio button 3"))
) # close conditional panel
), # close tab panel
id = "tabselected"
) # close tabsetPanel
) # close mainPanel
) # close pageWithSidebar
server <- function(input,output,session)({})
shinyApp(ui, server)
One way you can approach this is by updating the input choices with updateSelectInput
on the server side. If you define all combinations of countries, provinces, and variables in a dataframe, you can filter this dataframe according to user inputs.
In the simplified example below, the options for province(s) are updated based on the country selection. You could add a third layer for variable type with similar logic.
library(shiny)
df <- data.frame(
country = c(rep("U.S.", 2), rep("Canada", 2)),
province = c("California", "Oregon", "British Colulmbia", "Alberta")
)
ui <- fluidPage(
sidebarLayout(
sidebarPanel(
selectInput("country", "Country", unique(df$country), multiple = T),
selectInput("province", "Province:", "Select a country first", multiple = T)
),
mainPanel(
)
)
)
server <- function(input, output, session) {
observe({
# update options based on country selection
province_list <- df %>%
filter(country %in% input$country)
# update selector
updateSelectInput(session, "province", "Province:", choices = unique(province_list$province))
})
}
shinyApp(ui = ui, server = server)