加载 Shiny Application 时,如何避免初始加载时 sidebarMenu 中所有条件面板的闪烁?

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

在下面的代码中,我正在根据所选选项卡创建动态 sidebarMenu。在此应用程序的初始加载期间,即使只选择了 tab 1,也会呈现两个选项卡的 sidebarMenu。在我原来的应用程序中,这会导致加载时间延迟,因为我在每个选项卡上都有很多控件。

加载应用程序时,有没有办法只加载活动选项卡的侧边栏控件,而不是同时加载两个选项卡的侧边栏控件?

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) {
  }
)

我们可以使用 insertUI 和仅调用 onceobserveEvent 来实现:

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)
  }
)

ismirsehregal 的另一个回答帮助我更优雅地解决了这个问题。 思路取自之前的一篇post.

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"),
      style = "display: none;"
    ),
    conditionalPanel(
      condition = "input.main_tab == 'tab 2'",
      selectizeInput(inputId = "t2", label = "Select by:", choices = c(as.character(40:50))),
      print("Hello Tab 2"),
      style = "display: none;"
    )
  )
)


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) {
  }
)