3

Question

Why does a sliderInput() that's generated on the server, and rendered on the ui with uiOutput() not get displayed in a menuItem()?

Example

In this simple app I'm generating a sliderInput on the server (note the menuItem is deliberately commented out), and it works as expected

library(shiny)
library(shinydashboard)

rm(ui, server)

ui <- dashboardPage(
    dashboardHeader(),

    dashboardSidebar(
        sidebarMenu(
            #menuItem(text = "data options",
                      checkboxGroupInput(inputId = "cbg_group1", label = "group 1", 
                                         choices = c("some","check","boxes","to","choose","from") ),
                       uiOutput("sli_val1"),
                       checkboxGroupInput(inputId = "cbg_group2", label = "group 2", 
                                          choices = c("another","set","of","check","boxes") ),
            #                ),
            menuItem(text = "another tab")
            )
    ),
    dashboardBody()
)

server <- function(input, output, session){

    withProgress(message = "loading page", value=0.1, {
        ## simulate loading some data
        Sys.sleep(3)

        ## slider input
        output$sli_val1 <- renderUI({
            sliderInput(inputId = "sli_val1", 
                        label = "values", min = 0, max = 100,
                        value = c(25, 75) )
        })
        setProgress(value=1, detail="Complete")
    })
}

shinyApp(ui = ui, server = server)

However, when I move the uiOutput inside a menuItem( ), the output no longer renders:

ui <- dashboardPage(
    dashboardHeader(),

    dashboardSidebar(
        sidebarMenu(
            menuItem(text = "data options",
                     checkboxGroupInput(inputId = "cbg_group1", label = "group 1", 
                                        choices = c("some","check","boxes","to","choose","from") ),
                     uiOutput("sli_val1"),
                     checkboxGroupInput(inputId = "cbg_group2", label = "group 2", 
                                        choices = c("another","set","of","check","boxes") )
                             ),
            menuItem(text = "another tab")
            )
    ),
    dashboardBody()
)
Scopey
  • 6,269
  • 1
  • 22
  • 34
SymbolixAU
  • 25,502
  • 4
  • 67
  • 139

1 Answers1

8

At first, I'd change uiOutput("sli_val1") into uiOutput("out_sli_val1"), to prevent duplicated Ids.

Concerning your problem: This is an odd thing going on when Shiny runs through the document and renders/binds all possible outputs. The default action is to ignore all hidden output elements - that means not ignore completely (output "sli_val1" is bound alright), but their function is suspended, letting no children to be rendered.

So the problem is, that on initiation, this output is hidden in the subitem tree and from there on ignored.

The fix can be done by unsetting this supension behaviour by calling

outputOptions(output, "out_sli_val1", suspendWhenHidden = FALSE)

But how and where? This option has to be set before you run your "data loading". But it will throw errors, if output$out_sli_val1 has nothing assigned to it (is NULL). To avoid that, one can initialize an empty UI-chunk, which gets overridden on "data load".

Here is your minimal fix with 2 extra lines of code (and modified output Id):

library(shiny)
library(shinydashboard)

ui <- dashboardPage(
  dashboardHeader(),
  dashboardSidebar(
    sidebarMenu(
      menuItem(text = "data options", 
        checkboxGroupInput(inputId = "cbg_group1", label = "group 1", 
                           choices = c("some","check","boxes","to","choose","from") ),
        uiOutput("out_sli_val1"),
        checkboxGroupInput(inputId = "cbg_group2", label = "group 2", 
                           choices = c("another","set","of","check","boxes") )
      ),
      menuItem(text = "another tab")
    )
  ),
  dashboardBody()
)

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

  withProgress(message = "loading page", value=0.1, {
    ## simulate loading some data
    Sys.sleep(3)

    ## slider input
    output$out_sli_val1 <- renderUI({
      sliderInput(inputId = "sli_val1", label = "values", min = 0, max = 100, value = c(25, 75) )
    })

    setProgress(value=1, detail="Complete")
  })
}

shinyApp(ui = ui, server = server)
K. Rohde
  • 9,439
  • 1
  • 31
  • 51
  • Nice answer! How did you do debugging? – Mikael Jumppanen Apr 14 '16 at 07:19
  • 3
    @MikaelJumppanen I thought I read about that hidden issue somewhere. So I startet trying to manually unbind/bind the output (costom message handler + actionbutton) and looked at the HTML if the output div would react. And surpirisingly, it did as soon as the subMenu was visible. I tried linking unbind/bind to this visibility (would have been tideous) but found this more simple approach. The empty renderUI init was a hunch. – K. Rohde Apr 14 '16 at 07:36
  • I am not sure if this is intended behavior. – Mikael Jumppanen Apr 14 '16 at 08:04
  • @MikaelJumppanen And I am pretty sure it's not intended. – K. Rohde Apr 14 '16 at 08:40
  • @Symbolix Maybe you could write bug report. https://github.com/rstudio/shinydashboard/issues – Mikael Jumppanen Apr 14 '16 at 08:45
  • And I guess [this answer](http://stackoverflow.com/a/21535587/5977215) and explanation also apply too. Thanks For your answer. – SymbolixAU Apr 14 '16 at 22:29