Protect modal dialog in R Shiny

Viewed 353

I am working on a general error handler for a larger Shiny App. The idea is to open a specially styled modal dialog if an error occurs and thus notify the user that something went wrong. Since the app consists of several modules I think using a modal dialog in this case works best.

In general this already works fine, but when opening an error modal, any other modal can overwrite this error modal and thus the user might not even realise that an error occured. I don't want to stop the execution of the app when an error occurs, but want to notify the user and give him the chance to change his input and try again.

Is there a way to protect a modal from being overwritten by other modals?

Find a minimal example below. When choosing "success" all is great. But when choosing "error" you will only see the error modal because of the Sys.sleep() statement. Without it, it will be silently overwritten.

library(shiny)

# load example functions to 
source("example-functions.R")


# define UI
ui <- fluidPage(
  # application title
  titlePanel("Error Handler"),

  # sidebar with controls 
  sidebarLayout(
    sidebarPanel(
      radioButtons(inputId = "expected_outcome",
                   label = "Expected Outcome",
                   choices = list("Success", 
                                  "Error")),
      actionButton(inputId = "btn_start",
                   label = "Execute Test")
    ),

    # result message in main panel
    mainPanel(
      textOutput("user_message")
    )
  )
)

# server logic
server <- function(input, output) {
  # define a symbol for reactive values
  rv <- reactiveValues()
  # define a reactive variable to display output in the UI and initialise it
  rv$user_message <- "Hello World!"


  # handler of the user message  
  output$user_message <- renderText({
    rv$user_message
  })


  observeEvent(input$btn_start, {
    message("Start Button was pressed")
    # initialise result variable with `NULL`
    result <- NULL

    if (input$expected_outcome == "Success") {
      # set UI text for success
      rv$user_message <- "Success!"
    } else {
      # set UI text for error
      rv$user_message <- "Error!"

      # show a special error modal
      showModal(
        div(
          id = "general-app-error",
          modalDialog(
            title = "An error occured.",
            "This is the error explanation"
          )
        )
      )
      # wait for a second to demonstrate the effect
      Sys.sleep(1)
    }


    # this modal should simulate that some other modal could come up and 
    # overwrite an error modal so the user will not realise that an error
    # happened.
    showModal(
      modalDialog(
        title = "App modal",
        "This is the app modal, possibly overwriting other modals.",
        size = "m"
      )
    )
  }, ignoreInit = TRUE)
}

# Run the application 
shinyApp(ui = ui, server = server)
0 Answers
Related