R Shiny Dashboard does not load rendered UI inside of sidebarMenu on initialization

允我心安 提交于 2021-02-20 18:43:36

问题


I'm trying to generate a UI element that is dynamic based on how the user wishes to provide their input. I'm using the Shiny Dashboard for simplicity but I have encountered an issue with the sidebarMenu. Previously when I was placing static UI elements directly into the sidebarMenu, I had no issue, however when trying to place dynamic UI elements into the sidebarMenu I have problems. I'm using R 3.3.2 and Shiny 1.0.0 and Dashboard 0.5.3.

The specific problem I have is that when the program first loads up, the dynamic UI elements do not load. There does not appear to be any holdup in the code, as all the features of the interface work fine even while the dynamic UI is unloaded. I am able to get the dynamic UI to load by selecting one of the tabs in the navbar, or by hovering over something that I have implemented a tooltip on.

I am unable to provide the exact code but I have recreated a much smaller reproducible example that has all the same problems that my larger version does.

library("shiny")
library("shinydashboard")

header = dashboardHeader(
    title = "Dynamic UI Example"
)
sidebar = dashboardSidebar(
    sidebarMenu(
        menuItemOutput("dynamic_sidebar")
    )
)
body = dashboardBody(
    tabBox(
        tabPanel(
            strong("One")
        ),
        tabPanel(
            strong("Two")
        )
    )
)
ui = dashboardPage(header, sidebar, body)

server = shinyServer(function(input,output,session){
output$dynamic_sidebar = renderMenu({
        sidebarMenu(
            menuItem(
                "Slider or numeric problem",
                radioButtons("slider_or_numeric",
                   label = "Slider or Numeric Input",
                   choices = c("Slider", "Numeric"),
                   selected = "Slider",
                   inline = TRUE
                ),
                uiOutput("input")
            )     
        )
    })
    output$input = renderUI({
        if (input$slider_or_numeric == "Slider"){
            sliderInput("slider", 
                label = "slider",
                min = 0, max = 1,
                value = 0
            )
        } else {
            numericInput("numeric", 
                label = "numeric",
                min = 0, max = 1,
                value = 0
            )
        }
    })
})

shinyApp(ui, server)

To verify the problem, after loading it up just open the menu item and you'll see the radio buttons but nothing else. Switch the tab on the navbar from one to two, and the input should appear in the menu (must be done while the menu is open).

I'm really just grasping at straws here, I have been troubleshooting this for hours and I think it's just an incompatibility with these features. I'm really hoping someone can prove me wrong and show me that I'm just doing it wrong. I've already found alternatives for my main program but they don't have the same aesthetic with what I'm trying to accomplish here.

Thanks for any and all help!


回答1:


I think I found the issue, it was tricky, and took me awhile to find it. Although it is a small change, I will post the whole thing.

I think this is what you want:

library("shiny")
library("shinydashboard")

header = dashboardHeader(
  title = "Dynamic UI Example"
)
sidebar = dashboardSidebar(
  sidebarMenu(
    menuItemOutput("dynamic_sidebar")
  )
)
body = dashboardBody(
  tabBox(
    tabPanel(
      strong("One")
    ),
    tabPanel(
      strong("Two")
    )
  )
)
ui = dashboardPage(header, sidebar, body)

server = shinyServer(function(input,output,session){
  output$dynamic_sidebar = renderMenu({
    sidebarMenu(
      menuItem(
        "Slider or numeric problem",
        radioButtons("slider_or_numeric",
                     label = "Slider or Numeric Input",
                     choices = c("Slider", "Numeric"),
                     selected = "Slider",
                     inline = TRUE
        )
      ),   
      uiOutput("input")  # no longer in menuItem call
    )
  })
  output$input = renderUI({
    if (input$slider_or_numeric == "Slider"){
      sliderInput("slider", 
                  label = "slider",
                  min = 0, max = 1,
                  value = 0
      )
    } else {
      numericInput("numeric", 
                   label = "numeric",
                   min = 0, max = 1,
                   value = 0
      )
    }
  })
})
shinyApp(ui, server)

I think the problem was that uiOutput("input") somehow slipped into the menuItem call. This is a hazard with Shiny, and Shiny editors obviously need more support for showing this kind of scope.

Frankly I am a bit puzzled as to why it ever showed up when you played around with it. But enough...

While I am not completely sure I understand how you want this to work (it is just a toy example obviously), this is how it looks now at startup:

And here after the menu expansion and changing the input type via the newly exposed radio button control.




回答2:


So I have found a solution from another SO post: r shiny - uiOutput not rendering inside menuItem and I'm slightly ashamed I did not manage to find this in my first set of search efforts. To sum up what the post says in more detail, the UI element I am rendering inside the menuItem is initialized as hidden, and hidden items are suspended by default. As the post details, you can change this option via the outputOptions function. Here is an updated version that works exactly as I wanted it to originally:

library("shiny")
library("shinydashboard")

header = dashboardHeader(
    title = "Dynamic UI Example"
)
sidebar = dashboardSidebar(
    sidebarMenu(
        menuItemOutput("dynamic_sidebar")
    )
)
body = dashboardBody(
    tabBox(
        tabPanel(
            strong("One")
        ),
        tabPanel(
            strong("Two")
        )
    )
)
ui = dashboardPage(header, sidebar, body)

server = shinyServer(function(input,output,session){

    output$input <- renderUI({})
    outputOptions(output, "input", suspendWhenHidden = FALSE)

output$dynamic_sidebar = renderMenu({
        sidebarMenu(
            menuItem(
                "Slider or numeric problem",
                radioButtons("slider_or_numeric",
                   label = "Slider or Numeric Input",
                   choices = c("Slider", "Numeric"),
                   selected = "Slider",
                   inline = TRUE
                ),
                uiOutput("input")
            )     
        )
    })
    output$input = renderUI({
        if (input$slider_or_numeric == "Slider"){
            sliderInput("slider", 
                label = "slider",
                min = 0, max = 1,
                value = 0
            )
        } else {
            numericInput("numeric", 
                label = "numeric",
                min = 0, max = 1,
                value = 0
            )
        }
    })
})

shinyApp(ui, server)

Note that it is necessary to initialize the output object BEFORE setting it's options or else it would be null and cause an error.

Thanks to Mike for attempting to answer the question, hopefully if someone else stumbles onto this problem they'll find this solution useful.



来源:https://stackoverflow.com/questions/43080909/r-shiny-dashboard-does-not-load-rendered-ui-inside-of-sidebarmenu-on-initializat

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!