Search code examples
rshinydygraphs

dygraphs legend outside plot in shiny app for multiple plots


I have this shiny app where I'm plotting several dygraphs. Unfortunately, I dont't know how many plots there will be plottet. It may vary from time to time. So I came up with using uiOutput and renderUI to build an app that reacts on the number of plots. See https://shiny.rstudio.com/articles/dynamic-ui.html

Now I wnat to show the legend of each dygraph outside the respective plot as was shown here: Is there a way to add legend next to a dygraph in R, not exactly on the plot?

My problem is now that the <div> elements of the legend do not have the same height as the ones of the plots.

My code is:

UI:

library(dygraphs)
shinyUI(fluidPage(
 titlePanel("Simple example"),
 sidebarLayout(
  sidebarPanel(),
  mainPanel(
   fluidRow(column(10, uiOutput("graphs")),
            column(2, uiOutput("legends")))
   )
 )
))

server:

library(dygraphs)
library(xts)

shinyServer(function(input, output, session) {

# load xts sample data
data("sample_matrix")
sample.xts <- as.xts(sample_matrix)

output$graphs <- renderUI({ 
 plot_output_list <- lapply(1:3, function(i) { 
  dygraphOutput(paste0('div_graph_', i)) 
 }) 
})

output$legends <- renderUI({
 legend_output_list <- lapply(1:3, function(i) {
   htmlOutput(paste0("div_legende",i), height = "400px")
 })
})

# do the plotting
lapply(1:3, function(i) {
  output[[paste0('div_graph_', i)]] <- renderDygraph({
   dygraph(sample.xts[,i],main=i)%>%
    dyLegend(labelsDiv = paste0("div_legende",i), show = "always")
  })
 })
})

This leads to this plot, where you can see the legends of all three plots are directly pasted together. I want them to be right of their respective plot.

sample plot with legend


Solution

  • I got it. Creating a plotOutput and an empty plot does the trick:

    Ui stays the same. Server:

    library(dygraphs)
    library(xts)
    
    shinyServer(function(input, output, session) {
    
     data("sample_matrix")
     sample.xts <- as.xts(sample_matrix)
    
     output$graphs <- renderUI({ 
      plot_output_list <- lapply(1:3, function(i) { 
      dygraphOutput(paste0('div_graph_', i)) 
     }) 
    })
    
    output$legends <- renderUI({
     legend_output_list <- lapply(1:3, function(i) {
      plotOutput(paste0("div_legende",i), height = "400px")
     })
    })
    
    lapply(1:3, function(i) {
      output[[paste("div_legende",i)]] <- renderPlot(
        plot(1,1,type="n",xaxt="n",yaxt="n",ylab="",xlab="",bty="n"),
        height = "400px"
      )
      output[[paste0('div_graph_', i)]] <- renderDygraph({
      dygraph(sample.xts[,i],main=i)%>%
        dyLegend(labelsDiv = paste0("div_legende",i),
                 show = "always")
      })
     })
    })