0
votes

I'm working on building a R Shiny web app to help with data exploration. I have a main page with a row of tabs, and then a row of sub tabs: enter image description here

I want to have a panel appear that provides different inputs for users to select in order to create different charts (for example, when Bar Chart tab is selected, I'd like to have a dropdown list for the dataset columns, and when Histogram is selected, I'd like to have a slider for number of bins.

I can do this fine with the first level of tabs. For example, this following line of code in my ui.R allows me to easily render a panel whenever Correlation is selected:

conditionalPanel(
    condition = "input.tabs == 'correlation'",

    actionButton("generate_correlation", "Generate Heat Map")
  )

server.R:

      tabsetPanel(
        id = "tabs",

        tabPanel("Correlation", value = "correlation",
                 plotOutput("correlation"))

... code for other tabs...

However, I can't figure out how to access the value returned by the nested tabPanel (for example, Bar Chart or Histogram). I attempted to use this code:

tabPanel(
  "Visualize",
  value = "visualize",

  tabsetPanel(
    id = "vis_tabs",
    tabPanel("Bar Chart", value = "bar_tab",# <-- want a conditionalPanel to appear when this tab is selected

             plotOutput("bar_chart")),         
    tabPanel("Histogram", value = "histogram_tab",
             plotOutput("histogram"))
  )
),

with the following conditionalPanel:

  conditionalPanel(
    condition = "input.vis_tabs" == "bar_tab",
    #CODE HERE FOR INPUT STUFF TO APPEAR WHEN BAR CHART TAB IS SELECTED
  ),

But right now, the above conditionalPanel is always evaluating to true. This SO post is the closest I could find to an answer, and it really didn't help much since it was focused on display output.

My guess is that since the second-level tab is defined within the scope of the first level tab, the value it returns isn't available in the "global" ui.R or server.R scope. But if that's the case, I'd expect the conditionalPanel to always evaluate to false, while it's currently evaluating to always be true!

I also know that the condition being evaluated is in JavaScript, so would the nested tab condition be something like

input.tabs.vis_tabs == "bar_tab"

? I'm assuming that input is an instance of some Input JS object with tabs being a string property that is dynamically set as the user selects different tabs.

2
condition = "input.vis_tabs" == "bar_tab" contains a typo ;) Is it solved by condition = "input.vis_tabs == 'bar_tab' " ? Otherwise please provide a reproducible example. - Tonio Liebrand
@BigDataScientist figured it out. You were right- you also need to evaluate both first and second level tabs in the condition, since by default the first tab of the nested level is selected. - Yu Chen

2 Answers

2
votes

Here is complete example for non HTML expert (like me :D) based on @Yu Chen answer:

runApp(list(
  ui = shinyUI( fluidPage(

sidebarLayout( 
  sidebarPanel(
    conditionalPanel(condition="input.conditioned == 0",helpText("This is navnarMenu 0")),
    conditionalPanel(condition="input.conditioned == 1",helpText("This is navnarMenu 1")),
    conditionalPanel(condition= "input.Guidelines == 2.1 && input.conditioned == 2",helpText("This is navnarMenu 2")),
    conditionalPanel(condition= "input.Guidelines == 2.2 && input.conditioned == 2",helpText("This is navnarMenu 3"))),

  mainPanel(tabsetPanel(id='conditioned',

                        tabPanel("About", value=0),                   

                        tabPanel("Tab 1",value=1,tabsetPanel(
                          tabPanel("Tab 1.1"),
                          tabPanel("Tab 1.2", tabsetPanel(
                            tabPanel("Tab 1.2.1"),
                            tabPanel("Tab 1.2.2"))))),

tabPanel("Guidelines",value = 2, tabsetPanel( id = "Guidelines",         
                   navbarMenu("Tab 2.1",
                                   tabPanel("Tab 2.1.1",value=2.1),
                                   tabPanel("Tab 2.1.2",value=2.1)),

                 navbarMenu("Tab 2.2",
                                   tabPanel("Tab 2.2.1",value=2.2),
                                   tabPanel("Tab 2.2.2",value=2.2))))

  ))))),

server = function(input, output, session) {}


))
0
votes

I figured it out from a helpful SO user comment. First, of all, I had a typo in my conditional statement:

condition = "input.vis_tabs" == "bar_tab",

needs to be

condition = "input.vis_tabs == 'bar_tab'"

And from there, all tabsetPanel values can be referenced from input directly (they just need a unique id):

  conditionalPanel(
    condition = "input.vis_tabs == 'bar_tab' && input.tabs == 'visualize'",
    checkboxInput("save_data", "Save Data", FALSE)
  )

You need to make sure that you have both conditions evaluated to TRUE, since otherwise if bar_tab is the first nested tab, it is automatically selected by default. You want that conditional panel to only pop up when you have selected the appropriate first level tab AND second level tab.