#' Shiny Version of TryCatch
#'
#' Use in reactive context, i.e. inside a server function only.
#'
#' @param session the app session object
#' @param expr R expression to evaluate safely
#' @return NULL
#' @export
exec_safely <- function(session, expr) {
tryCatch(
withCallingHandlers(
warning=function(cnd) {
msg <- paste(conditionMessage(cnd), sep="\n")
shiny::showNotification(
ui=msg,
duration=10,
closeButton=TRUE,
type="warning"
)
},
message=function(cnd) {
msg <- paste(conditionMessage(cnd), sep="\n")
shiny::showNotification(
ui=msg,
duration=5,
closeButton=TRUE,
type="message"
)
},
expr
),
error=function(cnd) {
msg <- paste(conditionMessage(cnd), sep="\n")
shiny::showNotification(
ui=msg,
duration=10,
closeButton=TRUE,
type="error"
)
}
)
}
demo_exec_safely <- function() {
stopifnot(
require(shiny),
require(shinydashboard)
)
nm <- "Demo: exec_safely"
ui <- shinydashboard::dashboardPage(
header=shinydashboard::dashboardHeader(title=nm),
sidebar=shinydashboard::dashboardSidebar(),
body=shinydashboard::dashboardBody(
shiny::fluidRow(
shiny::column(3, shiny::textInput("x", label="x:")),
shiny::column(1, shiny::actionButton("btn","Click me", style = "margin-top:25px;")), # vertically aligned
shiny::column(2, shiny::h2(shiny::textOutput("log_x_formatted")))
)
),
title=nm
)
server <- function(input, output, session) {
rv <- shiny::reactiveValues()
shiny::observeEvent(input$btn, exec_safely(session,{ # redirect warnings etc. to ShowNotification
x <- suppressWarnings(as.numeric(input$x))
stopifnot(is.numeric(x) && !is.na(x))
rv[["log_x"]] <- log(x)
}))
output$log_x_formatted <- shiny::renderText(sprintf("%.3f", rv[["log_x"]]))
}
shiny::runApp(shiny::shinyApp(ui, server))
}