24

I would like to display different inputs for different tabs. So I tried to build a page with several tabPanels. However, I can't have sth like below:

library(shiny)

shinyUI(pageWithSidebar(
  headerPanel("Header"),

  tabsetPanel(
    tabPanel(
      headerPanel("Tab 1"),
      sidebarPanel(
        selectInput("var", "Parametre", choices = c("1", "2", "3"))
        ),
      mainPanel(
        textOutput("text1")
        )
      ),
    tabPanel(
      headerPanel("Tab 2"),
      sidebarPanel(
        selectInput("var", "Parametre", choices = c("21", "22", "23"))
      ),
      mainPanel(
        textOutput("text2")
      )
    )
    )
  ))

I suspect that the pageWithSidebar is causing the problem, but I couldn't find an alternative in google groups. Is there a way to display several tabs with their own sidebars and mainPanels, or shall I create different apps for this purpose?

Phil
  • 7,287
  • 3
  • 36
  • 66
barerd
  • 835
  • 3
  • 11
  • 31
  • Please add your dataframe to the question. – Abbas Apr 25 '13 at 21:53
  • @barerd make a toy example dataframe that illustrates your problem. e.g. something *simillar* to `data.frame( ID = seq(10) , Yas = runif(10) , Hosp = rep( c("A","B" ) , 5 ) )` – Simon O'Hanlon Apr 25 '13 at 22:25

3 Answers3

24

If I do not misunderstand your question, I think you can even evade the jQuery part (from @f1r3br4nd answer) by supplying an id for the tabsetPanel function, here id = "conditionedPanels". The value parameter (i.e. which tab is selected in the main panel) is then available via the input variable.

A minmal example: server.R may be empty except for the shinyServer function skeleton. The ui.R file might be as follows.

shinyUI(pageWithSidebar(
  headerPanel("Conditional Panels"),
  sidebarPanel(
    conditionalPanel(condition="input.conditionedPanels==1",
                     helpText("Content Panel 1")
    ),
    conditionalPanel(condition="input.conditionedPanels==2",
                     helpText("Content Panel 2")
    ) 
  ),
  mainPanel(
    tabsetPanel(
      tabPanel("Panel 1", value=1), 
      tabPanel("Panel 2", value=2)
      , id = "conditionedPanels"
    )
  )
))
Mark Heckmann
  • 10,943
  • 4
  • 56
  • 88
  • You will find more on this here: https://groups.google.com/forum/#!topic/shiny-discuss/07EU9xG11l0 – Mark Heckmann Jun 22 '13 at 12:59
  • Could you please explain what the `1` and `2` are supposed to represent? In practice, my `tabPanel()` commands usually have something like `tabPanel("Panel 2", uiOutput("blah"))`, so perhaps you could expand your answer to include handling common situations like this? – warship Sep 10 '16 at 06:57
  • @warship It is the `value` you choose in `tabPanel` – Mark Heckmann Sep 11 '16 at 10:40
  • I understand, but how is this related to (or rather, how can this be applied to) situations like `tabPanel("Panel 2", uiOutput("blah"))` or `tabPanel("Panel 2", plotOutput("blah2"))`? I'm having a hard time adapting your code above to situations like this because I don't use `value=`. – warship Sep 12 '16 at 03:54
  • @warship For the above approach to work, you *must* supply the `value` argument... Otherwise you have to somehow solve this using jQuery as done in the other answer. – Mark Heckmann Sep 12 '16 at 07:30
10

I got mine to work by having only one sidebarPanel like in the Shiny example apps but then wrapping stuff in the sidebarPanel that's only for specific tabs in separate conditionalPanel calls as here. The trick is then to make the character string that is conditionalPanel's condition argument be a jQuery statement that looks at the html attribute of the currently selected tab and ===s it to the name of the tab for which this content should appear in the sidebar:

conditionalPanel(
    "$('li.active a').first().html()==='Foo'",
    actionButton("bar","Bar"));

...where Foo is the title of the tab.

In short, one sidebar but its content conditional on active tab.

bokov
  • 3,444
  • 2
  • 31
  • 49
  • 2
    Thank you for this and some other answers about R, which I read via your profile. – barerd Jun 20 '13 at 22:29
  • Although I like this solution, I think the supported solution is that by @mark-heckmann. See his solution in this thread and his link to the google groups in the comment. I would recommend to the OP that he accept his response as the solution. – ctbrown Sep 10 '14 at 15:46
2

I know this is an old post but I stumbled across it when I was looking for an answer to a similar question. I think you can also accomplish what you want by using a fluidPage (instead of pageWithSidebar) and then using the sidebarLayout function in each of the tabPanels.

An example:

library(shiny)

ui <- fluidPage(
  headerPanel("Header"),
  tabsetPanel(
    tabPanel('Tab 1',
             sidebarLayout(
               sidebarPanel(
                 selectInput("var", "Parametre", choices = c("1", "2", "3"))
               ),
               mainPanel(
                 textOutput("text1")
               )
             )  
    ),
    tabPanel('Tab 2',
             sidebarLayout(
               sidebarPanel(
                 selectInput("var", "Parametre", choices = c("21", "22", "23"))
               ),
               mainPanel(
                 textOutput("text2")
               )
             )
    )
  )
)

server <- function(input, output) {}

shinyApp(ui, server)