Shiny: why are either inserted tabs or input value displayed?

Hello,

The minimal code below is a simple shiny app that has one slider to select the number of tabs to show - and next to it, it should display the selected number and the tabs.

But it only shows the selected number or the tabs, but not both. Why is this the case and what to do?

I need both (I want to display some data from a database that depend on the selected number).

library(shiny)
 
ui <- fluidPage(   
    sidebarLayout(
        sidebarPanel( 
          sliderInput("nr_tabs", "Number of tabs:",
                      min = 1, max = 5, value = 3)
        ), 
        mainPanel(
          uiOutput("myOutput"),
        )
    )
)

server <- function(input, output, session) {
  old_nr_of_tabs <- 0
  
  output$myOutput <- renderUI({ 
      tagList(
        # if next line is inserted, no tabs are displayed
        # tags$h2(paste0("Tabs: ", input$nr_tabs)),
        tabsetPanel(id = "myTabs")
      )
  })
    
  observe({ 
    input$nr_tabs  
    if (old_nr_of_tabs > 0) {
      for (i in 1:old_nr_of_tabs) { 
        removeTab("myTabs", toString(i))  
      }
      old_nr_of_tabs <<- 0 
    } 
    if (input$nr_tabs > 0) {
      for (i in 1:input$nr_tabs) { 
        insertTab("myTabs", tabPanel(
          title = toString(i), value = toString(i),
          tags$p(paste("I'm tab", i))), select = TRUE)  
      }
    }
    old_nr_of_tabs <<- input$nr_tabs  
  })
}
 
shinyApp(ui = ui, server = server)

I think you have a timing issue, where theres no guarantee that a myTabs exists in the browsers DOM when some number of tags are requested to remove/add from it.
I noted that your original code even with the print out commented out, doesnt show the tabs until the slide is moved, even though the slider should have an initial value 3 and show 3 tabs.

By far the easiest way to approach this; is to have myTabs be more concrete; i.e. fixed in the UI so you have more guarantees about its presence when you run your server code.

library(shiny)

ui <- fluidPage(   
  sidebarLayout(
    sidebarPanel( 
      sliderInput("nr_tabs", "Number of tabs:",
                  min = 1, max = 5, value = 3)
    ), 
    mainPanel(
      uiOutput("myOutput"),
      tabsetPanel(id = "myTabs")
    )
  )
)

server <- function(input, output, session) {
  old_nr_of_tabs <- 0
  
  output$myOutput <- renderUI({ 
       tags$h2(paste0("Tabs: ", input$nr_tabs))

  })
  
  observe({ 
    input$nr_tabs  
    if (old_nr_of_tabs > 0) {
      for (i in 1:old_nr_of_tabs) { 
        removeTab("myTabs", toString(i))  
      }
      old_nr_of_tabs <<- 0 
    } 
    if (input$nr_tabs > 0) {
      for (i in 1:input$nr_tabs) { 
        insertTab("myTabs", tabPanel(
          title = toString(i), value = toString(i),
          tags$p(paste("I'm tab", i))), select = TRUE)  
      }
    }
    old_nr_of_tabs <<- input$nr_tabs  
  })
}

shinyApp(ui = ui, server = server)

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

If you have a query related to it or one of the replies, start a new topic and refer back with a link.