Reputation: 3236
I would like to make the data behind my shiny refreshable upon user's request. However, as the refresh takes several minutes, I would like to warn the user before actually starting the process and allow them to cancel.
I use the super shinyalert
package by @deanattali to setup the alert. Here is a small reproducible example. Think of data(mtcars)
as fetching some data, and the average calculation as some data processing, both of which takes some time.
library(shiny)
library(shinyalert)
library(data.table)
ui <- bootstrapPage(
useShinyalert(),
actionButton("refresh", "Refresh"),
dataTableOutput("table")
)
server <- function(input, output) {
observeEvent(input$refresh, {
shinyalert("You are abouto to refresh data...", showCancelButton = TRUE)
})
aggregated_data <- eventReactive(input$shinyalert, {
message("reload data")
data(mtcars)
as.data.table(mtcars)[, .(avg_speed = mean(mpg)), by = cyl]
}, ignoreNULL = FALSE)
output$table <- renderDataTable(
aggregated_data()
)
}
shinyApp(ui, server)
However, it does not work as I want. It reloads the data whenever input$shinyalert
changes, not when the user clicked "OK" (I know this is the expected functionality, I just don't know how to achieve the functionality I want). How can I rewrite this to recalculate aggregated_data
reactive only if the input$shinyalert changed to TRUE
?
(I tried a simple if statement within the eventReactive
but it does not return anything if the condition evaluates to FALSE
.)
Upvotes: 2
Views: 1656
Reputation: 1302
You are using eventReactive
the wrong way. This isn't working as expected because shinyalert
returns FALSE
if you click cancel
and thus, triggers eventReactive
- see shinyalert github readme
When there is no input field in the modal, the value of the modal is TRUE if the user clicked the “OK” button, and FALSE if the user clicked the “Cancel” button.
Try reactiveValues
instead of eventReactive
and use req()
inside the observer which ignores FALSE
values
server <- function(input, output) {
observeEvent(input$refresh, {
shinyalert("You are abouto to refresh data...", showCancelButton = TRUE)
})
aggregated <- reactiveValues()
observe({
req(input$shinyalert)
message("reload data")
data(mtcars)
aggregated$data <- as.data.table(mtcars)[, .(avg_speed = mean(mpg)), by = cyl]
})
output$table <- renderDataTable(
aggregated$data
)
}
Also, if you like to set up the ignoreNULL = FALSE
again, you can specify this with the creation of aggregated
Upvotes: 2