shiny app will not work if the same "output" is used two times in Ui.R

Created on 25 Feb 2015  路  6Comments  路  Source: rstudio/shiny

If the same "output" slot is referenced two times in Ui.R, the browser will not output results nor will the shiny app issue any errors for debugging.

I do not know if this is more of a browser issue than that of shiny, but I think some kind of warning/error message would be appropriate in this case.

Below is example code for reproducing the issue.

Server.R:

library(shiny)

shinyServer(function(input, output) {

  output$distPlot <- renderPlot({

    # generate bins based on input$bins from ui.R
    x    <- faithful[, 2]
    bins <- seq(min(x), max(x), length.out = input$bins + 1)

    # draw the histogram with the specified number of bins
    hist(x, breaks = bins, col = 'darkgray', border = 'white')

  })

Ui.R

library(shiny)

shinyUI(fluidPage(

  # Application title
  titlePanel("Old Faithful Geyser Data"),

  # Sidebar with a slider input for number of bins
  sidebarLayout(
    sidebarPanel(
      sliderInput("bins",
                  "Number of bins:",
                  min = 1,
                  max = 50,
                  value = 30)
    ),

    # Show a plot of the generated distribution
    mainPanel(
      h3("Example text"),
      plotOutput("distPlot"),
      plotOutput("distPlot")

    )
  )
))

Most helpful comment

You don't need the same id to show the same thing. The easiest way would be to encapsulate all your logic and input dependencies in a reactive and then use that in the appropriate places. Ex:

library(shiny)
library(datasets)

# Define UI
ui <- fluidPage(
  selectInput('data', 'Choose dataset', c('cars', 'faithful')),
  numericInput('obs', 'How many obs to include?', 5),
  plotOutput('p1'),
  plotOutput('p2')
)

# Server logic
server <- function(input, output, session) {

  currentData <- reactive({
    data <- switch(input$data,
              "cars" = cars, "faithful" = faithful)
    head(data, n = input$obs)
  })

  output$p1 <- renderPlot({
    plot(currentData())
  })

  output$p2 <- renderPlot({
    plot(currentData())
  })
}

# Complete app with UI and server components
shinyApp(ui, server)

All 6 comments

Yes, Shiny doesn't support multiple outputs with the same name. This code would generate HTML where two elements have the same ID, which is invalid HTML.

I agree that it would be nice to have a warning/error for this. Unfortunately isn't a simple way to do this. The validation process would require Shiny looking at the entire HTML document and checking for multiple instances of each ID. Presently there's nothing like this in Shiny, although it might not be a bad idea to add a validation stage that checks for this and other things.

I think there's an error message in the JavaScript console of the browser at least. Although admittedly those are easy to miss.

Sorry to come up with this again, but is there an easy way to display things twice? Let's assume I'd like to show the same plotOutput in two different tabs of a shiny app. I understand it's not easily possible because of the invalid HTML / id thing, but I wonder whether there is an easy way to 'reference' to another output.

You don't need the same id to show the same thing. The easiest way would be to encapsulate all your logic and input dependencies in a reactive and then use that in the appropriate places. Ex:

library(shiny)
library(datasets)

# Define UI
ui <- fluidPage(
  selectInput('data', 'Choose dataset', c('cars', 'faithful')),
  numericInput('obs', 'How many obs to include?', 5),
  plotOutput('p1'),
  plotOutput('p2')
)

# Server logic
server <- function(input, output, session) {

  currentData <- reactive({
    data <- switch(input$data,
              "cars" = cars, "faithful" = faithful)
    head(data, n = input$obs)
  })

  output$p1 <- renderPlot({
    plot(currentData())
  })

  output$p2 <- renderPlot({
    plot(currentData())
  })
}

# Complete app with UI and server components
shinyApp(ui, server)

Or you can try modularising your app , using shiny modules. There's a link here to help https://www.ardata.fr/en/post/2019/02/11/why-using-modules/

The example provided by @bborgesr can be reduced a little more by using:

  output$p2 <- output$p1 <- renderPlot({
    plot(currentData())
  })
Was this page helpful?
0 / 5 - 0 ratings

Related issues

FrissAnalytics picture FrissAnalytics  路  5Comments

dmpe picture dmpe  路  4Comments

jiayi9 picture jiayi9  路  5Comments

hudon picture hudon  路  4Comments

howardcoleman picture howardcoleman  路  5Comments