Reputation: 1707
I have a Shiny app with produces the following output. I would like the height of the graph to scale to fill the row which contains the sidebar, (down to some minimum dimension). This sidebar height changes depending on the data being examined.
The ui code I'm currently using is:
sidebarLayout(
sidebarPanel(
uiOutput("ridgeDates")
),
mainPanel(
plotOutput("ridgesPlot")
)
)
with the plot being rendered by renderPlot(...)
This seems to adjust the /width/ automatically as I change the browser window width.
I've spent a while searching but can't find anything that does this. Is this possible?
Upvotes: 0
Views: 228
Reputation: 2613
We can use jQuery to track the height of the sidebar and set the height of the plot in css before creating the plotOutput. To do that, we need to use uiOutput in the UI, then render the plot dynamically.
So in the UI, the mainPanel will now have:
uiOutput("ridgePlot")
Then the plot is rendered in the server like so:
output$ridgePlot <- renderUI({
# plot data
output$ridges <- renderPlot({
# plot()
})
plotOutput("ridges")
})
Now we use shinyjs()
to write a simple javascript function that sets the height value of the plot to the height of the sidebar. The sidebar is of class well
, so we first get the height of the well, save it to a variable then set the ridges plot to the height of the variable, in javascript like this:
var newHeight = $('.well').outerHeight(); $('#ridges').height(newHeight)
I have used .outerHeight()
because the well has extra padding that effectively gives it extra height than the height specified in the css rules for the well.
We can use this function in shiny using runjs()
from shinyjs
package. Since we need to get the height from the well after it has been rendered, we use observe and use it before the plotOutput
inside the renderPlot, which is also inside the renderUI.
observe({
session$onFlushed(function() {
shinyjs::runjs("var newHeight = $('.well').outerHeight(); $('#ridges').height(newHeight)")
}, once=TRUE)
})
Putting it together in one Shiny app:
library(shiny)
library(shinyjs)
library(ggplot2)
ui = fluidPage(
useShinyjs(),
titlePanel("This is just a test!"),
sidebarLayout(
sidebarPanel(
uiOutput("ridgeDates")
),
mainPanel(
uiOutput("ridgePlot")
))
)
server = function(input, output, session) {
output$ridgeDates <- renderUI({
rng <- round(runif(1, 15, 21))
radioButtons("choose", "A changing list", choices = 1:rng)
})
output$ridgePlot <- renderUI({
datax <- matrix(c(1,2,3,4,5,6),6,1)
datay <- matrix(c(1,7,6,4,5,3),6,1)
titleplot<-"title"
summary <- "testing text"
output$ridges <- renderPlot({
# pl <- plot(datax, datay, main = titleplot, xlab = "input$axis1", ylab = "input$axis2", pch=18, col="blue")
ggplot(NULL, aes(datax, datay))+
geom_point(colour = "#1e90ff")
})
observe({
session$onFlushed(function() {
shinyjs::runjs("var newHeight = $('.well').outerHeight(); $('#ridges').height(newHeight)")
}, once=TRUE)
})
plotOutput("ridges")
})
}
# Run the application
shinyApp(ui = ui, server = server)
My example:
Upvotes: 2