Search code examples
rshinyshinydashboardshiny-servershinyapps

How to avoid initial loading with flickering of all conditionalPanels in sidebarMenu while Shiny Application loads?


In the code below, I am creating a dynamic sidebarMenu based on the selected tab. During the initial load of this application, the sidebarMenu for both tabs is rendered even though only tab 1 is selected. In my original application, this is causing a delay in loading time as I have a lot of controls on each tab.

While application loads, is there a way to load only the sidebar controls of the active tab instead of loading sidebar controls of both the tabs?

library(shiny)
library(shinydashboard)

sidebar <- dashboardSidebar(
  collapsed = FALSE,
  sidebarMenu(
    id = "menu_sidebar",
    conditionalPanel(
      condition = "input.main_tab == 'tab 1'",
      selectizeInput(inputId = "t1", label = "Select by:", choices = c(as.character(30:40))),
      print("Hello Tab 1")
    ),
    conditionalPanel(
      condition = "input.main_tab == 'tab 2'",
      selectizeInput(inputId = "t2", label = "Select by:", choices = c(as.character(40:50))),
      print("Hello Tab 2")
    )
  )
)


body <- dashboardBody(
  fluidRow(
    tabsetPanel(
      id = "main_tab",
      selected = "tab 1",
      tabPanel(title = "tab 1", "Tab content 1"),
      tabPanel(title = "tab 2", "Tab content 2")
    )
  )
)


shinyApp(
  ui = dashboardPage(
    dashboardHeader(title = "tabBoxes"),
    sidebar,
    body
  ),
  server = function(input, output) {
  }
)

Solution

  • We can use insertUI along with an observeEvent which is called only once to achive this:

    library(shiny)
    library(shinydashboard)
    
    sidebar <- dashboardSidebar(
      collapsed = FALSE,
      sidebarMenu(
        id = "menu_sidebar",
        conditionalPanel(
          condition = "input.main_tab == 'tab 1'",
          selectizeInput(inputId = "t1", label = "Select by:", choices = c(as.character(30:40))),
          div("Hello Tab 1")
        ))
    )
    
    body <- dashboardBody(
      fluidRow(
        tabsetPanel(
          id = "main_tab",
          selected = "tab 1",
          tabPanel(title = "tab 1", "Tab content 1"),
          tabPanel(title = "tab 2", "Tab content 2")
        )
      )
    )
    
    shinyApp(
      ui = dashboardPage(
        dashboardHeader(title = "tabBoxes"),
        sidebar,
        body
      ),
      server = function(input, output, session) {
        observeEvent(input$main_tab == 'tab 2', {
          insertUI(
            selector = "#menu_sidebar",
            where = "afterEnd",
            ui = conditionalPanel(
              condition = "input.main_tab == 'tab 2'",
              selectizeInput(inputId = "t2", label = "Select by:", choices = c(as.character(40:50))),
              div("Hello Tab 2")
            ),
            immediate = TRUE,
            session = getDefaultReactiveDomain()
          )
        }, ignoreInit = TRUE, once = TRUE)
      }
    )