Jan Kislinger
Jan Kislinger

Reputation: 1563

R Shiny: Output functions don't work within eventReactive()

I want to modify UI using uiOutput() and plotOutput() when the button is clicked. Everything works fine if it doesn't wait for the event and changes the content immediately. What should i change to make output$body.on.button having the same output as output$body.immediately when the button is clicked?

server.R:

shinyServer(function(input, output, session) {

  output$plot <- renderPlot({plot(1:5)})
  output$body.ui <- renderUI({tags$p('This works only within renderUI')})

  output$body.on.button <- eventReactive(input$goButton, {
    switch(
      input$select,
      "text" = 'This works within both functions',
      "ui" = uiOutput("body.ui"), # This doesn't work
      "plot" = plotOutput("plot") # This doesn't work
    )
  })

  output$body.immediately <- renderUI({
    switch(
      input$select,
      "text" = 'This works within both functions',
      "ui" = uiOutput("body.ui"), # This works
      "plot" = plotOutput("plot") # This works
    )
  })
})

ui.R:

library(markdown)

shinyUI(
  navbarPage(
    "Title",

    tabPanel(
      "First element",
      fluidRow(

        column(
          4,
          wellPanel(
            selectInput("select", "Select", c('text', 'ui', 'plot')),
            actionButton("goButton", "Go!")
          ) # end of wellPanel
        ), # end of column

        column(
          4,
          uiOutput("body.immediately")
        ), # end of column

        column(
          4,
          uiOutput("body.on.button")
        ) # end of column


      ) # end of fluidROw
    ) # end of tabPanel
  ) # end of navbarPage
) # end of shinyUI

I have also tried function observeEvent() but it didn't help.

Upvotes: 2

Views: 1770

Answers (1)

Michal Majka
Michal Majka

Reputation: 5471

It doesn't work because you can't have two outputs with the same ID. In your example "Text" works because it is just a text - not an output with an ID.

In the example below I've added three new outputs with unique IDs. uiOutput body.on.button also dynamically receives a specific output after clicking on a button.


You can try to remove this three lines

output$text2 <- renderText({ 'This works within both functions' })
output$body.ui2 <- renderUI({tags$p('This works only within renderUI')})
output$plot2 <- renderPlot({plot(1:10)})

and then change IDs within eventReactive from "text2" to "text" (similarly with the other two) to see that the outputs after clicking on a button are not going to be shown.

If you want to have, for example, two same plots, then you should create two plotOutputs with unique IDs and then use twice renderPlot functions which produce the same plots.

I hope this helps.


Full example:

server <- shinyServer(function(input, output, session) {

  # Create outputs with unique ID

  output$text <- renderText({ 'This works within both functions' })
  output$body.ui <- renderUI({tags$p('This works only within renderUI')})
  output$plot <- renderPlot({plot(1:5)})

  output$text2 <- renderText({ 'This works within both functions' })
  output$body.ui2 <- renderUI({tags$p('This works only within renderUI')})
  output$plot2 <- renderPlot({plot(1:10)})


  # Save the selected type of the output and then pass it to renderUI via react()
  react <- eventReactive(input$goButton, {
    switch(
      input$select,
      "text" = textOutput("text2"),
      "ui" = uiOutput("body.ui2"), 
      "plot" = plotOutput("plot2") 
    )
  })

  output$body.on.button <- renderUI({
    react()
  })

  output$body.immediately <- renderUI({
    switch(
      input$select,
      "text" = textOutput("text"),
      "ui" = uiOutput("body.ui"), # This works
      "plot" = plotOutput("plot") # This works
    )
  })
})


  library(markdown)


ui <-shinyUI(
  navbarPage(
    "Title",

    tabPanel(
      "First element",
      fluidRow(

        column(
          4,
          wellPanel(
            selectInput("select", "Select", c('text', 'ui', 'plot')),
            actionButton("goButton", "Go!")
          ) # end of wellPanel
        ), # end of column

        column(
          4,
          uiOutput("body.immediately")
        ), # end of column

        column(
          4,
          uiOutput("body.on.button")
        ) # end of column


      ) # end of fluidROw
    ) # end of tabPanel
  ) # end of navbarPage
) # end of shinyUI
shinyApp(ui, server)

Upvotes: 3

Related Questions