Search code examples
rinputshinyconditional-statements

Conditional input still appearing in Shiny after condition is no longer met when using `observe()` and `renderUI()`


I have a conditional input that I want present in the sidebar panel only when a previous input has a certain value. Unlike when using conditionalPanel() and if i use if statements, the conditional input is created with renderUI() and displayed accordingly when the condition is met. However, when the condition is no longer met, the conditional input does not disappear even if the code for the such input is inside observe(). Here is a minimal example:

library(shiny)

ui <- fluidPage(
  
  # Application title
  titlePanel("Conditional input"),
  
  sidebarLayout(
    sidebarPanel(
      
    
      
      selectInput(inputId = "input1",
                  label = "Input1",
                  choices = c("A","B"),
                  selected = "A"),
      
      uiOutput(outputId = "input2")
  
  

    ),
    mainPanel()
    
      
      
    )
  )


server <- function(input, output){

  observe(
    
    if(input$input1 == "B"){
      
      output$input2 = renderUI({
        
        selectInput(inputId = "input2",
                    label = "Input2",
                    choices = c("option1",
                                "option2"))
      })
    }
   
  
  )
}

shinyApp(ui = ui, server = server)

Initially:

enter image description here

With the appropiate choice in input1, the conditional input2 shows up:

enter image description here

However, when going back to choice in input1 that no longer meets the condition needed to have input2, such input2 remains displayed:

enter image description here

As mentioned above, when using conditionalPanel() the conditional input appears/disappears as expected, but is it possible to make it work also as shown in the minimal example with some small modification?

Thanks!


Solution

  • Here's a simple solution that gives you what you want.

    library(shiny)
    
    ui <- fluidPage(
      titlePanel("Conditional input"),
      sidebarLayout(
        sidebarPanel(
          selectInput(inputId = "input1",
                      label = "Input1",
                      choices = c("A","B"),
                      selected = "A"
          ),
          uiOutput(outputId = "uiPanel")
        ),
        mainPanel()
      )
    )
    
    server <- function(input, output){
      output$uiPanel <- renderUI({
        if (input$input1 == "B") {
          selectInput(inputId = "input2",
                          label = "Input2",
                          choices = c("option1", "option2")
          )
        }
      })
    }
    
    shinyApp(ui = ui, server = server)
    

    The renderUI returns NULL if input$input1 == "A". Note that I've renamed the uiOutput to avoid the clash of IDs and refactored the code to remove the redundant call to observe(). This isn't necessary because the reference to input$input1 inside the renderUI call is all that's necessary to trigger a call whenever needed.