R Shiny - add tabPanel to tabsetPanel dynamically (with the use of renderUI)
Asked Answered
C

2

51

I am developing a shiny application in which I use tabsetPanel, which is generated when user enters some particular input. Thus, I want to use renderUI function to make a tabsetPanel appear / disappear.

My struggle now is that number of tabPanel elements (arguments of tabsetPanel) also depends on user input, in the way: sometimes I need 1 one, other times I want more tabPanels.

How to make it? I tried including conditionPanel or including simple if()... condition in the tabsetPanel argument, but it (rather not surprisingly...) did not work.

Cerberus answered 19/10, 2013 at 19:53 Comment(0)
C
86

Here you go. The code is fairly self explanatory.

library(shiny)
runApp(list(
  ui = pageWithSidebar(
    headerPanel('Dynamic Tabs'),
    sidebarPanel(
      numericInput("nTabs", 'No. of Tabs', 5)
    ),
    mainPanel(
      uiOutput('mytabs')  
    )
  ),
  server = function(input, output, session){
    output$mytabs = renderUI({
      nTabs = input$nTabs
      myTabs = lapply(paste('Tab', 1: nTabs), tabPanel)
      do.call(tabsetPanel, myTabs)
    })
  }
))
Canaigre answered 19/10, 2013 at 20:6 Comment(4)
Glad to be of help. If you have any questions on the code itself, post here.Canaigre
Add on: Once you have the added tabs, what is the proper way to add the same uiOutput to all tabs, but make the values unique within each tab? Or is this different? If you add an output$base_tab_ui and render them in each, all of them hold the same input$value for each tab. Is there a way to make these unique with different input variable names?Elidaelidad
@Canaigre how would you go about populating each of these dynamic tabs with its own content? perhaps, say, a renderTable / tableOutput of a data.frame which can be filtered using the same object I used to populate the tab names (ie nTabs = length(lags_7) and myTabs = lapply(sprintf('%s', lags_7), tabPanel)) (possible answer here: #39276604)Bartolomeo
@d8aninja, assuming that you have some plots added to a list called myPlots, you can do: nTabs = length(myPlots); myTabs = lapply(1:nTabs, function(x){tabPanel(paste0("Tab ",x), renderPlot(myPlots[[x]]))}); do.call(tabsetPanel, myTabs)Enchanting
N
4

There is a way to dynamically add tabPanels without renderUI, which might not be as obvious as the version with renderUI. I wrote a function addTabToTabset which will append any (list of) tabPanel(s) to a tabset/navbar.

This approach has a set of advantages over using renderUI:

  • Existing tabPanels are not re-rendered each time a new panel is added. (faster)
  • Thus, not resetting all the input variables inside existing Panels. (no variable storing workarounds needed)
  • Structure of the panel contents can be chosen individually. (In the lapply - renderUI version, all panels have to be somewhat uniform.)

The solution and code sample can be found in the answer here. If requested, I could also post the code here.

Neopythagoreanism answered 17/4, 2016 at 8:28 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.