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:
- Funnel 1: User selects a country to analyze. In the Shiny example below each tab is for a different country. User selects the country to analyze
- Funnel 2: User selects a province within the country to analyze. A list of provinces for the country the user selected in the tab manifests in this sidebar panel
- Funnel 3: User wants to find demographic/other data for the selected province. A group of action buttons appears for each of the province statistics offered up for analysis, such as average rainfall, average temperature, homicide rate, population, average incomes, etc. Selecting an action button clears out the main panel and a series of prompts appear in that main panel for the user to continue with inputs for the analysis, with a back button to go back to the original main panel of action buttons. For the sake of brevity, these action buttons / back button aren't rendered in the image or in the code below
- Carousel: along the top of the main panel, when the user goes to an action button in that main panel, a carousel of radio button choices appear for actions like show data, show plot, download the data, etc.
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)
CodePudding user response:
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)