I am using a for loop to create multiple popping up messages in my shiny app (using shinyalert package). I would like messages to stop popping if user had clicked Cancel as an answer to a previous message. Below a sample of code illustrating my example
library(shiny)
library(shinyalert)
ui <- fluidPage(
actionButton("run", "Run")
)
server <- function(input, output, session) {
observeEvent(input$run, {
vector.elements <- c("A", "B", "C", "D", "E")
decision <<- TRUE
for (element in vector) {
shinyalert(
title = "Do you accept following element?",
text = element,
showCancelButton = TRUE,
callbackR = mycallback)
mycallback <- function(value) {
decision <<- value
}
if (decision == FALSE) {
break
}
}
})
}
shinyApp(ui = ui, server = server)
If user clicks on Cancel button as an answer to Do you accept following element? A, I would like next messages not to pop up.
Any hint would be much appreciated!
Shiny alert does not seem to be run synchronous to the loop. Put
print(decision)
in front of the for-loop. It'll show in the console that the loop runs independently from the user clicking on the alert messages. That means: it won't work with a for loop or any other loop. It can only be done using the event mechanisms provided by Shiny.The solution below creates and manipulates a reactive value
RequiredAnswers
. Any change to it will trigger the shiny alert to open and ask the user to confirm the first element of theRequiredAnswers
vector. In other words, it removes the element that has just been answered with "No".Each answer to the alert will be caught by
observeEvent(input$AnswerAlert, {})
. If the response was "cancel" it dismisses the first element ofRequiredAnswers
thus triggering the next alert. This way we get a loop. If the response was "Ok" it will clearRequiredAnswers
and no more alerts will be triggered (becauseobserveEvent(RequiredAnswers(), {})
does not respond toRequiredAnswers == NULL
.Drawback: if the user clicks 'Cancel' quite fast, Shiny does not recognize the event
observeEvent(input$AnswerAlert, {})
does not get called. I cannot say for sure what the source of this is. My guess is a bug in Shiny Alert.Another way would be to do it recursively (see the section "Chaining modals" in the documentation). This way, the lost events may be avoided.