My problem with breaking a loop insidse shinyalert has been solved in this post.
I decided to try "Chaining modals" approach.
The approach seems to work in my case, hovewer I am facing another problem-
as I am not using any loop, values are not used as a parameter anymore (vector "all.elements" is not being used).
In my case it is a little bit a problem, because in my original app "elements" to be checked are being selected beforewards and only a part of vector elements should be included in "shinyalert" part.
For this reason I would like to keep "vector of elements" with elements selected beforewards. Elements not included in the vector should be skipped in the chain of modals (in the example element "C" should be skipped, that means "Do you accept element C?" message should not pop up even if elements "A" and "B" had been previously confirmed by a user).
App should proceed from "Do you accept element B?" to "Do you accept element D?" question directly
I was trying to achieve that using ifelse function inside my shinyalert but I have not succeeded.
Is there way to do that? Below the code I wrote using "Chaining modals" approach.
library(shiny)
library(shinyalert)
ui <- fluidPage(
actionButton("run", "Run")
)
server <- function(input, output, session) {
observeEvent(input$run, {
all.elements <- c("A", "B", "C", "D", "E")
selected.elements <- c("A", "B", "D", "E")
shinyalert(
title = "Do you accept element A?",
showCancelButton = TRUE,
callbackR = function(value) {
ifelse(value == TRUE,
shinyalert(title = "Do you accept element B?",
showCancelButton = TRUE,
callbackR = function(value) {
ifelse(value == TRUE, shinyalert(title = "Do you accept element C?",
showCancelButton = TRUE,
callbackR = function(value) {
ifelse(value == TRUE, shinyalert(title = "Do you accept element D?",
showCancelButton = TRUE, callbackR = function(value) {
ifelse(value == TRUE,
shinyalert(title = "Do you accept element E?",
showCancelButton = TRUE), decision <<- "STOP")}), decision <<- "STOP")}), decision <<- "STOP")}), decision <<- "STOP")}
)
})
}
shinyApp(ui = ui, server = server)
Another thing I noticed, when I click "OK" quickly, sometimes the consecutive message does not appear. Maybe there is a way to do similar thing using Modals approach built in Shiny, without using the shinyalert library?
Use shinyWidgets::confirmSweetAlert
instead. I have noticed this bug in shinyalert chaining before, and you need to ask the author to fix it. Instead, I always use sweetalert from shinyWidgets
. Besides, when the call back chain is long, it looks very ugly. It's called the callback hell: http://callbackhell.com/.
See below how I solve the problem with confirmSweetAlert
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
actionButton("run", "Run")
)
server <- function(input, output, session) {
observeEvent(input$run, {
all.elements <- c("A", "B", "C", "D", "E")
selected.elements <- c("A", "B", "D", "E")
confirmSweetAlert(session, "comfirmA", "Do you accept element A")
})
observeEvent(input$comfirmA, {
req(input$comfirmA)
confirmSweetAlert(session, "comfirmB", "Do you accept element B")
})
observeEvent(input$comfirmB, {
req(input$comfirmB)
confirmSweetAlert(session, "comfirmC", "Do you accept element C")
})
observeEvent(input$comfirmC, {
req(input$comfirmC)
confirmSweetAlert(session, "comfirmD", "Do you accept element D")
})
observeEvent(input$comfirmD, {
req(input$comfirmD)
confirmSweetAlert(session, "comfirmE", "Do you accept element E")
})
}
shinyApp(ui = ui, server = server)
OK, coming back to your question, how do we do the chain automatically and skip some items.
library(shiny)
library(shinyWidgets)
ui <- fluidPage(
actionButton("run", "Run")
)
server <- function(input, output, session) {
all.elements <- c("A", "B", "C", "D", "E")
selected.elements <- c( "B", "D", "E")
excluded_index <- which(!all.elements %in% selected.elements)
comfirm_text <- c(
"Do you accept element A",
"Do you accept element B",
"Do you accept element C",
"Do you accept element D",
"Do you accept element E"
)
observeEvent(input$run, {
confirmSweetAlert(session, paste0("comfirm", selected.elements[1]), comfirm_text[-excluded_index][1])
})
lapply(seq_along(selected.elements)[2:length(selected.elements)], function(x) {
observeEvent(input[[paste0("comfirm", selected.elements[x -1])]], {
req(input[[paste0("comfirm", selected.elements[x -1])]])
confirmSweetAlert(
session,
paste0("comfirm", selected.elements[x]),
comfirm_text[-excluded_index][x]
)
})
})
}
shinyApp(ui = ui, server = server)
selected.elements
selected.elements
from 2 to end.