I have a fluid row that contains two conditional panels. I would to make it so that if only one is being displayed, it takes up the entire row (width = 12), whereas if both are showing they both get equal space (width = 6).
I have attempted to use multiple conditional panels based on logic of whether one or both are turned on, but it ends up showing all of the panels regardless of the value of either of the inputs.
When I comment out either the first two conditional panels OR the 3rd one, the logic works fine - so it isn't the individual logic, it's something that isn't working when all 3 are evaluated.
So, is there something I'm doing wrong here? Is there a better option than having multiple conditional panels for the same content, such as a method for having them automatically take up as much width as is available?
fluidRow(
conditionalPanel(condition = "input.chart_toggle && !input.table_toggle",
box(title = "Chart",
width = 12,
collapsible = F,
collapsed = F,
plotOutput("newplot")
)
),
conditionalPanel(condition = "input.table_toggle && !input.chart_toggle",
box(title = "Table",
width = 12,
collapsible = F,
collapsed = F,
DTOutput("table")
)
),
conditionalPanel(condition = "input.chart_toggle && input.table_toggle",
box(title = "Chart",
width = 6,
collapsible = F,
collapsed = F,
plotOutput("newplot")
),
box(title = "Table",
width = 6,
collapsible = F,
collapsed = F,
DTOutput("table")
)
)
Having multiple identical ids for different inputs/outputs is never a good idea. It will most certainly result in unexpected behaviour.
That said, using conditionalPanel
seems to complicate things a bit.
As @Meisam stated in the comments, you can use renderUI
and then put the conditions there.
Another alternative would be to use {shinyjs}
to hide and show the cards, and then update them as required.
Here is a reprex:
global.R
library(shiny)
ui.R
ui <- bs4Dash::bs4DashPage(
header = bs4Dash::dashboardHeader(),
sidebar = bs4Dash::dashboardSidebar(),
body = bs4Dash::dashboardBody(
shinyjs::useShinyjs(),
checkboxInput(
inputId = "chart_toggle",
label = "Show chart",
value = TRUE
),
checkboxInput(
inputId = "table_toggle",
label = "Show table",
value = TRUE
),
fluidRow(
bs4Dash::bs4Card(
id = "chart_card",
title = "Chart",
width = 6,
collapsible = FALSE,
plotOutput("newplot")
),
bs4Dash::bs4Card(
id = "table_card",
title = "Table",
width = 6,
collapsible = FALSE,
DT::DTOutput(outputId = "table")
)
)
)
)
server.R
server <- \(input, output, session) {
output$newplot <- renderPlot({
plot(
x = iris$Sepal.Length,
y = iris$Petal.Width,
col = iris$Species,
xlab = "Sepal Length",
ylab = "Petal Width",
pch = 19
)
})
output$table <- DT::renderDT({
DT::datatable(
iris,
options = list(scrollX = TRUE)
)
})
observeEvent(c(input$chart_toggle, input$table_toggle), {
chart_toggle <- input$chart_toggle
table_toggle <- input$table_toggle
if (chart_toggle && !table_toggle) {
shinyjs::hide(id = "table_card")
bs4Dash::updatebs4Card(
id = "chart_card",
action = "update",
options = list(width = 12)
)
shinyjs::show(id = "chart_card")
}
if (!chart_toggle && table_toggle) {
shinyjs::hide(id = "chart_card")
bs4Dash::updatebs4Card(
id = "table_card",
action = "update",
options = list(width = 12)
)
shinyjs::show(id = "table_card")
}
if (chart_toggle && table_toggle) {
bs4Dash::updatebs4Card(
id = "chart_card",
action = "update",
options = list(width = 6)
)
bs4Dash::updatebs4Card(
id = "table_card",
action = "update",
options = list(width = 6)
)
shinyjs::show(id = "chart_card")
shinyjs::show(id = "table_card")
}
if (!chart_toggle && !table_toggle) {
shinyjs::hide(id = "chart_card")
shinyjs::hide(id = "table_card")
}
})
}