1
votes

The following minimal example demonstrates a problem with updating nested outputs followed by updating the inputs with the content they had before the update of the outputs. This minimal example comes from a much larger project, so solutions to the problem like "don't nest the outputs" aren't viable unless Shiny doesn't actually allow nested outputs.

When you run the example, you'll see two radio buttons and a text input. Enter some text and change the radio button. You will see that after the radio button event is handled, the text input has indeed been updated. But if you change the radio button a second time, the text input at the observeEvent() will be blank.

It's like the updateTextInput() function works fine for updating what you see in the browser, but not at all for what Shiny gets back from the browser for that input on the next event.

To add a bit of strange, also note that if you change the updated text input in any way (e.g., add or remove one character to/from it), then it works as expected. Is the problem here my code, my expectations, or a bug in Shiny?

ui <- fluidPage(fluidRow(column(12, tagList(
         uiOutput("outer_div")
      ))))

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

updateScreen = function() {
   output$outer_div = renderUI(uiOutput("inner_div"))
   output$inner_div = renderUI(tagList(
      radioButtons(inputId = "button", label="", choices = c("A", "B")),
      textInput("text", label="", value="")
   ))
}
updateScreen()   #initialize screen

   observeEvent(input$button, {
      print(paste0("Text input is ", input$text))
      updateTextInput(session, inputId = "text" , value=input$text)
      updateRadioButtons(session, inputId="button", selected=input$button)
      updateScreen()
   })

}

shinyApp(ui = ui, server = server)
1
Probably insertUI in Shiny 0.14 is a better solution than nested UI. - Xiongbing Jin
What exactly is the GOAL of this? I can think of a few solutions...but want to be sure i'm not wasting anyone's time. - Carl Boneri
A few things I just noticed. You're attempting to update a text input based on a response to any change in the radio-group...BUT...you're updating the text input to whatever the current value of the input is. This isn't going to update anything if I'm reading your code execution correctly. Also; where is the print() function cat'ing itself to? Also; calling updateScreen ouside of a reactive and then again in an observer would create a fight no? - Carl Boneri
In the larger project, the radio buttons designate different citation databases (PubMed, Embase, etc.). When you pick one the screen adapts to collect the information needed to upload a local citation file obtained from that source. If you fill out one of these fields, e.g. the name of the search, and then switch databases, I'd like to retain that name. But switching databases starts with empty inputs. The updateTextInput() replaces what was there and works as far as browser display goes. Print() goes to the RStudio console for debugging. The first updateScreen() only runs at startup. - 3D0G

1 Answers

0
votes

Does this work for you?

ui <- fluidPage(fluidRow(column(12, tagList(
  uiOutput("outer_div")
))))

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

  updateScreen = function() {
    output$outer_div = renderUI(uiOutput("inner_div"))
    output$inner_div = renderUI(tagList(
      radioButtons(inputId = "button", label="", choices = c("A", "B")),
      textInput("text", label="", value="")
    ))
  }
 updateScreen()   #initialize screen


    data <- isolate(input$text)
  observeEvent(input$button, {
    updateTextInput(session, inputId = "text" , value=data)
    updateRadioButtons(session, inputId="button", selected=input$button)
    print(paste0("Text input is ", input$text))
    #updateScreen()
  })

}

shinyApp(ui = ui, server = server)