Inconsistent state of dependent UI elements

Hi,
I have the following problem. There are three UI elements, two inputs and one output. The range of choices of the second input depends on the first input. Let's say the first is a checkbox, the second a selection. The output only makes sense if the second UI element is updated to reflect the first. If not, the two selections are incompatible and result in an error. The app works, but the inconsistent state happens and error messages flash in red briefly during updates. Not a show stopper, but it doesn't look professional either. I can catch the errors and just output an empty something, this is not about finding some workaround. I was wondering if there is a solution that prevents the output from being updated before the two inputs are and if there is something fundamental about reactive programming that I am still missing that results in this problem. Somewhat minimal example below. To reproduce, click the checkbox. Thanks!


ui <- fluidPage(

   # Application title
   titlePanel("Dependencies"),

   # Sidebar with a slider input for number of bins
   sidebarLayout(
      sidebarPanel(
         checkboxInput(inputId = "uppercase",label = "Uppercase?", value = TRUE)
      ),
      selectInput(inputId = "letters",
                  label = "Select letter",
                  choices = LETTERS,
                  selected = "A")),
      mainPanel(
         textOutput(outputId = "textOut")
      )
   )


server <- function(input, output, session) {
  output$textOut <- renderText({
    stopifnot(all(input$letters %in% if (input$uppercase)
      LETTERS
      else
        letters))
    input$letters
  })



  observeEvent(input$uppercase, updateSelectInput(
    session = session,
    inputId = "letters",
    label = "Select letters",
    choices = if(input$uppercase) LETTERS else letters,
    selected = if(input$uppercase) "A" else "a"
    ))
}

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

Shiny provides various ways to guard against 'improper' states, for example the req() function,
in your case I think using the validate() and need() functions, is the most appropriate.
Rather than flash a message in need(), I will just set an empty string message, so that the output text box is simply blank when in the inappropriate state.

 output$textOut <- renderText({
  validate(
    need(all(input$letters %in% if (input$uppercase) {
      LETTERS
    } else {
      letters
    }), "")
  )
  input$letters
})

This topic was automatically closed 54 days after the last reply. New replies are no longer allowed.

That's what I call a workaround and I can do the same without validate and need (no need to rename if-then-else, they are just fine). You are still producing the output and the screen is going to flash empty. I was wondering if there was a way to prevent the inconsistent state from arising, to always evaluate the select input before the textOut. What's happening is that I change the checkbox, textout is refreshed in an inconsistent state, select input is updated, then textout is refreshed in a consistent state. I would like to make that sequence checkbox -> selectInput -> textOutput. You see? Three steps instead of four and no inconsistent state. Is my question more clear now?