afleishman
afleishman

Reputation: 433

Plotting the same output in two tabPanels in shiny

I'm trying to plot the same histogram in two separate tab panels within a tabBox in shiny. I can plot the data in one of the tabs, but then when I add the code for the other it seems to break the app. Below is an example of I'm trying to do:

    library(shiny)
     library(dplyr)

data(mtcars)

body <- dashboardBody(
  fluidRow(
    tabBox(
      title = "miles per gallon",

      id = "tabset1", height = "250px",
      tabPanel("Tab1", plotOutput("plot1")),
      tabPanel("Tab2", plotOutput("plot1"), "test") # the app 'breaks' when I add in the **plotOutput("plot1")** here... however it works when I remove it
    )
    )
  )

shinyApp(
  ui = dashboardPage(
    dashboardHeader(title = "Test"),
    dashboardSidebar(),
    body
  ),
  server = function(input, output) {


      output$plot1 <- renderPlot({hist(mtcars$mpg)})

  }
)

In this particular example, I could just add another line in the server like this

 output$plot2 <- renderPlot({hist(mtcars$mpg)})

and then call plot2, but my actual app is a bit more complex than the above example, so I'd like to plot plot1 in both tabs.

Upvotes: 3

Views: 2067

Answers (2)

B&#225;rbara Borges
B&#225;rbara Borges

Reputation: 919

BigDataScientist's answer is great and very scalable.

But for situations where you only have one or two outputs that you want to repeat, I think the easiest and most readable solution is to assign them all to the same render function. For example, this would be:

output$plot1 <- output$plot2 <- renderPlot({ hist(mtcars$mpg) })

Here's the full working app using this solution:

library(shiny)

body <- dashboardBody(
  fluidRow(
    tabBox(title = "miles per gallon", id = "tabset1", height = "250px",
      tabPanel("Tab1", plotOutput("plot1")),
      tabPanel("Tab2", plotOutput("plot2"), "test")
    )
  )
)

shinyApp(
  ui = dashboardPage(
    dashboardHeader(title = "Test"),
    dashboardSidebar(),
    body
  ),
  server = function(input, output) {
    output$plot1 <- output$plot2 <- renderPlot({ hist(mtcars$mpg) })
  }
)

Upvotes: 5

Tonio Liebrand
Tonio Liebrand

Reputation: 17689

When you create a shiny app, you are creating a HTML site and the outputs are in div containers with ids. So what you are trying without knowing is to create two div container with the same id. This will not work. For a discussion, see here: Can multiple different HTML elements have the same ID if they're different elements?

What you can do is to wrap the server code in a lapply()function and generate two ids:

lapply(1:2, function(nr){
  output[[paste0("plot", nr)]] <- renderPlot({hist(mtcars$mpg)})      
})

and then call plotOutput("plot1") and plotOutput("plot2"). There are also other possibilities to use only one output in a combination with conditionalPanels(), but i think this way should work better for you.

Upvotes: 5

Related Questions