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.