rshinyrenderui

Update dynamically rendered UI in bsModal


I want to use bsModal that contains inputs that are generated via renderUI. The inputs depend on my data but will not change after start-up. When opening the modal I want to update the selected values of the input. The problem is that in my minimal reproducible example the first update goes wrong as the inputs inside the modal have not been rendered, yet. From the second update on everything works fine.

Here is the example:

library(shiny)
library(shinyBS) 

ui <- fluidPage(

    titlePanel("Modal Update Problem"),
    
    actionButton(inputId = "btn_test", label = "Click Me"),
    bsModal("modal_test", "Test Modal", "btn_test", size = "large",
            
            uiOutput("test_ui")
    )
    
    
)

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

    observeEvent(input$btn_test, {
        updateSelectInput(
            session = session,
            inputId = "test_select",
            selected = "B"
        )
    })
    
    output$test_ui <- renderUI({
        selectInput(
            inputId = "test_select",
            label = "Test",
            choices = c("A", "B", "C"),
            selected = "A"
        )
    })
}

# Run the application 
shinyApp(ui = ui, server = server)

Expected behaviour: Select-Input inside the modal shows "B" every time I click the button. Current behaviour: It shows "A" (i.e. the initial value) after the first click and "B" after the second click.

Is there a clean solution to do this or at least a workaround? How can I render the UI inside the modal on start-up?


Solution

  • Just using selectInput inside observeEvent displays your expected behavior as shown below. Does your use case require you to use updateSelectInput? If so, you can use outputOptions as shown below.

    ui <- fluidPage(
      
      titlePanel("Modal Update Problem"),
      
      actionButton(inputId = "btn_test", label = "Click Me"),
      bsModal("modal_test", "Test Modal", "btn_test", size = "large",
              
              uiOutput("test_ui")
      )
    )
    
    server <- function(input, output, session) {
      
      observeEvent(input$btn_test, {
        updateSelectInput(
          session = session,
          inputId = "test_select",
          selected = "B"
        )
      })
      
      output$test_ui <- renderUI({
        selectInput(
          inputId = "test_select",
          label = "Test",
          choices = c("A", "B", "C") , 
          selected = "A"
        )
      })
      outputOptions(output, "test_ui", suspendWhenHidden = FALSE) 
      
    }
    
    # Run the application 
    shinyApp(ui = ui, server = server)