Jan Kislinger Jan Kislinger - 3 months ago 20
R Question

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.

Answer

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)