I am working on an App where the user needs to walk through 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, without leading into dead ends, etc. For example, funneling a user from general to more specific choices:
- Funnel 1: Very general choices (first and 2nd images image below: Tab 1 and Tab 2)
- Funnel 2: Less general choices (first image below: in sidebar panel)(2nd image: in sub-tabs)
- Funnel 3: Most specific choices (first image below: radio buttons along top of main panel)(2nd image: in sidebar panel)
My question is, is it possible to create something like the sub-panels I drew in the 2nd image, to provide an easy funnel for user choices (albeit prettier than my drawing)? If not, in Shiny what are the other options for efficiently funneling a user through choices, if any? Where I'm heading is in the first image where the user goes from Tabs - sidebar - radio buttons across the top of the main panel.
Reproducible code for first 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:
You can nest a tabsetPanel()
inside an existing tabPanel()
.
library(shiny)
shinyApp(
fluidPage(
sidebarLayout(
sidebarPanel(
"here is your sidebar",
uiOutput("tab_controls"),
uiOutput("subtab_controls")
),
mainPanel(
tabsetPanel(
tabPanel(
"Tab 1", br(),
tabsetPanel(
tabPanel("Function 1", "Here's the content for Tab 1, Function 1, with a `br()` between parents and sub-tab"),
tabPanel("Function 2", "Here's the content for Tab 1, Function 2, with a `br()` between parents and sub-tab"),
id = "subtab_1"
)
),
tabPanel(
"Tab 2",
tabsetPanel(
tabPanel("Function 1", "Here's the content for Tab 2, Function 1, with no space between tab levels"),
tabPanel("Function 2", "Here's the content for Tab 2, Function 2, with no space between tab levels"),
id = "subtab_2"
)
),
tabPanel("Tab 3", "Here's some orphaned content without sub-tabs"),
id = "parent_tabs"
)
)
)
),
function(input, output, session) {
output$tab_controls <- renderUI({
choices = if (input$parent_tabs == "Tab 1") {
c("choices", "for", "tab 1")
} else if (input$parent_tabs == "Tab 2") {
c("tab 2", "settings")
}
if (length(choices)) {
radioButtons(
"tab_controls",
"Controls",
choices = choices
)
}
})
output$subtab_controls <- renderUI({
if (input$parent_tabs == "Tab 2" & input$subtab_2 == "Function 1") {
radioButtons(
"subtab_controls",
"Additional controls for Tab 2, Function 1",
choices = letters[1:5]
)
} else if (input$parent_tabs == "Tab 2" & input$subtab_2 == "Function 2") {
selectInput(
"subtab_controls",
"Different input for Tab 2, Function 2",
choices = letters[6:10]
)
}
})
}
)
Here I've got three tabs at the top level, Tab 1-3. Inside Tab 1 and Tab 2, there are tabsetPanel
s that each have two tabs for Functions 1-2.
Also I showed two approaches (there are others, like update____Input
functions) to changing the controls in the sidebar depending on which tab is selected. You should specify each tab set with tabsetPanel(..., id = "something")
. Then you can check input$something
's value, which will be the title of one of its tabs.