Currently, I am working on crafting a shiny app that utilizes sidebarLayout() and the goal is to display either one or two plots side by side in the mainPanel(). The decision on how many plots to show is based on an input value set in the sidebarPanel().
In scenarios where only one plot is required, I aim for that plot to occupy 100% of the horizontal space within the mainPanel. Conversely, if both plots need to be displayed, each should take up 50% of the mainPanel space.
Specifically, I also want the contents of each column to utilize all available horizontal space within their respective columns.
I have experimented with various approaches:
Utilizing a fluidRow() with a column and a conditionalPanel()
- This method encountered challenges as fluidRow() expects width parameters from each element, while conditionalPanel() seemed incompatible.
Employing conditionalPanel() in the right part of a splitLayout()
- However, this approach merely hides the right-hand side and does not enable the left plot to expand to occupy all the mainPanel() space.
Integrating a conditionalPanel() inside a right div with display: table-cell property
- Unfortunately, this yielded similar outcomes as mentioned above.
library(ggplot2)
library(shiny)
ui <- fluidPage(
tags$head(
tags$style("
#my_container {
display: table;
width: 100%;
}
.col {
display: table-cell;
}
#col_left {
background-color: #ffa;
}
#col_right {
background-color: #faf;
}
")
),
sidebarPanel(
checkboxInput("checkbox",
"View Both",
value = TRUE),
width = 2
),
mainPanel(
div(id = "my_container",
div(id = "col_left",
class ="col",
plotOutput("plot_output_1")),
div(id = "col_right",
class = "col",
conditionalPanel("input.checkbox == 1",
plotOutput("plot_output_2")))
),
width = 10
)
)
server <- shinyServer(function(input, output) {
output$plot_output_1 <- renderPlot({
ggplot(
data.frame(x = runif(3), y = rnorm(3)),
aes(x = x, y = y)) +
geom_point()
})
output$plot_output_2 <- renderPlot({
ggplot(
data.frame(x = runif(3), y = rnorm(3)),
aes(x = x, y = y)) +
geom_point()
})
})
shinyApp(ui, server)
- Another attempt involved incorporating JavaScript mechanisms to adjust the div widths.
- While successful in hiding the right column and revealing the left column, the left plot did not automatically readjust to fill the new space despite being redrawn due to input dependency.
library(ggplot2)
library(shiny)
ui <- fluidPage(
tags$head(
tags$style("
#my_container {
display: table;
width: 100%;
}
.my_col {
display: table-cell;
}
#col_left {
background-color: #ffa;
}
#col_right {
background-color: #faf;
}
"
),
tags$script("
Shiny.addCustomMessageHandler('n_show.onchange', function(value) {
var col_left = document.getElementById('col_left');
var col_right = document.getElementById('col_right');
if(value == 'one') {
col_left.style.width = '100%';
col_right.style.width = '0%';
} else {
col_left.style.width = '50%';
col_right.style.width = '50%';
}
});
"
)
),
sidebarPanel(
selectInput(inputId = "n_show", label = "Number of Plots", choices = c("one", "two"), selected = "two"),
width = 2
),
mainPanel(
div(id = "my_container",
div(id = "col_left",
class = "my_col",
plotOutput("plot_output_1")),
div(id = "col_right",
class = "my_col",
conditionalPanel("input.n_show == 'two'",
plotOutput("plot_output_2")))
),
width = 10
)
)
server <- shinyServer(function(input, output, session) {
output$plot_output_1 <- renderPlot({
input$n_show
ggplot(
data.frame(x = runif(3), y = rnorm(3)),
aes(x = x, y = y)) +
geom_point()
})
output$plot_output_2 <- renderPlot({
input$n_show
ggplot(
data.frame(x = runif(3), y = rnorm(3)),
aes(x = x, y = y)) +
geom_point()
})
observeEvent(input$checkbox, {
session$sendCustomMessage("n_show.onchange", input$n_show)
})
})
shinyApp(ui, server)
My conviction is that this task is not overly complex, but my familiarity with CSS seems insufficient - particularly in the realm of shiny application development.