1

I would like to implement collapsible columns in R Shiny, in a way that is intuitive and leaves as much non-interactive UI code in ui.R.

I've figured out a couple ways to make collapsible columns. One is to put the entire UI into a call to renderUI in server.R, and render different layouts based on an input condition, like so:

shinyApp(
    ui = fluidPage(
        uiOutput("panels"),
        checkboxInput("showSidePanel", "Show Side Panel", TRUE)
    ), 
    server = function(input, output) {
        output$panels <- renderUI(
            if (input$showSidePanel) {
                fluidRow(
                    column(4,
                           wellPanel(h2("Side Panel"))
                    ),
                    column(8,
                           wellPanel(h2("Main Panel"))
                    )
                )
            }
            else
                wellPanel(h2("Main Panel")))
    }
)

However, this is not extensible (imagine adding several more optional panels), and the structure of the code doesn't reflect its function. Also, it's unintuitive and ugly to have entire UI sitting in a single renderUI call, while ui.R is nearly empty.

Another option is to use move away from bootstrap and use fillRow():

shinyApp(
    ui = fluidPage(
        fillRow(flex = c(NA, 1), height = 100,
                uiOutput("sidePanel"),
                wellPanel(h2("Main Panel"))
        ),
        checkboxInput("showSidePanel", "Show Side Panel", TRUE)
    ), 
    server = function(input, output) {
        output$sidePanel <- renderUI(
            if (input$showSidePanel) {
                wellPanel(h2("Side Panel"))
            } else {
                NULL
            }
        )
    }
)

This is extensible and while the UI still resides entirely in the server code, at least it is logically divided up. However it still seems counter-intuitive to put a bunch of non-interactive UI into my server code just to make it collapsible [my actual side-panel is made up of many UI elements]. Is there a simple or logical way to do this that I am missing? If possible I'd like to stick with the fluidPage/fluidRow/column approach to the UI.

mb7744
  • 390
  • 2
  • 12
  • are you open to using `conditionalPanel()`? it may be easier if you don't need to responsive content, but just show/hide functionality – Nate Feb 20 '17 at 16:31
  • When one panel/column is hidden, I want the other(s) to grow to fill in the space. However my ideal solution would be something of the same form as `conditionalPanel`, just with my desired functionality. I might take a crack at developing something like that. – mb7744 Feb 20 '17 at 18:40
  • You can use `hide` and `show` functions from `shinyjs` package to hide or show columns. You could give an id to each element in the ui and call the function. It could be something in the lines of [this](http://stackoverflow.com/a/42272709/5894457) – SBista Feb 24 '17 at 06:08

0 Answers0