0
votes

Problem Summary

I have searched thoroughly and I could not find anyone who had asked this same question. I am making a chemical reaction simulation webpage using R Shiny and want to display variables from the most recent simulation to the user. Thus a user can change input variables, but until the action button is pressed again and another reaction simulated, the displayed "variable summary panel" should not change.

The implementation should have been fairly straightforward using observeEvent, renderUI, and htmlOutput, but I have been having issues with the "variable summary panel" reacting to changes in input variables, even without the action button being pressed. Here is some example code:

Example Code

library(shiny)
library(tidyverse)

ui <- fluidPage(
   # input variable
   tags$p("Reaction Temperature  (ºC)"),
   sliderInput("temp_initial",NULL,min = 20,max = 70,value = 25),
   # action button
   actionButton(inputId = "go", label = "Generate Reaction Simulation"),
   # summary panel
   wellPanel(
       tags$p(tags$strong("Simulated input variables")),
       htmlOutput("blurb_explanation")
   )
)
server <- function(input, output, session) {
    # render summary panel text
    observeEvent(input$go, ({
        output$blurb_explanation <- renderUI(
           HTML(paste("<strong>   Reaction Temperature (ºC) --></strong>", input$temp_initial))
        )
    })
    )
}
# Run the application 
shinyApp(ui = ui, server = server)

Attempted Solutions

I may just have a lack of understanding of Shiny reactivity as I am fairly new to R Shiny. My understanding is that if I pass in input$go as the reactive expression to observeEvent, the body of the function will not run until the go button is pressed again. Right now, after the summary panel is made, any updates in the slider still change the HTML output.

I've tried wrapping the function body in an isolate function, making the observeEvent dependent on other reactive variables, and nothing seems to fix this reactivity problem.

Thank you in advance for your help, this is my first Stack Overflow question, let me know if anything is unclear and I can try to fix.

1

1 Answers

2
votes

By default, your renderUI - just like any renderXXXX - updates in response to changes to any if the reactives that it contains. So it updates in response to both a click on your actionButton AND to the sliderInput. You can't get rid of its dependency on the sliderInput, so you need to isolate the renderUI from changes to the sliderInput. Fortunately, the isolate function does that for you.

Here's a working version of your server function:

server <- function(input, output, session) {
  # render summary panel text
  observeEvent(input$go, ({
    output$blurb_explanation <- renderUI(
      isolate(HTML(paste("<strong>   Reaction Temperature (ºC) --></strong>", input$temp_initial)))
    )
  })
  )
}

A simpler version would remove the need for renderUI or observeEvent:

server <- function(input, output, session) {
  # render summary panel text
    output$blurb_explanation <- renderText({
      input$go
      isolate(HTML(paste("<strong>   Reaction Temperature (ºC) --></strong>", input$temp_initial)))
    })
}

The renderText still depends on the actionButton, so it updates in response to clicks on the button. But the actionButton generates no output. The htmlOutput's dependency on the sliderInput is still masked by isolate so the output updates only to button clicks.

PS. Welcome to SO.