From bad6d44422019c1d1bba048214ecc789b38a197b Mon Sep 17 00:00:00 2001 From: pvictor Date: Sun, 5 Sep 2021 18:35:29 +0200 Subject: [PATCH] inputSweetAlert(): allow javascript code, for example inputValidator option --- R/sweetalert.R | 35 +++++++++++-------- examples/sweetalert-input.R | 9 ++++- .../assets/sweetalert2/sweetalert-bindings.js | 8 ++++- man/inputSweetAlert.Rd | 12 ++++++- tests/testthat/test-SweetAlert.R | 2 +- 5 files changed, 48 insertions(+), 18 deletions(-) diff --git a/R/sweetalert.R b/R/sweetalert.R index 51277953..a595bdff 100644 --- a/R/sweetalert.R +++ b/R/sweetalert.R @@ -356,6 +356,7 @@ ask_confirmation <- function(inputId, #' \code{"password"},\code{"textarea"}, \code{"radio"}, \code{"checkbox"} or \code{"select"}. #' @param inputOptions Options for the input. For \code{"radio"} and \code{"select"} it will be choices. #' @param inputPlaceholder Placeholder for the input, use it for \code{"text"} or \code{"checkbox"}. +#' @param inputValidator JavaScript function to validate input. Must be a character wrapped in \code{I()}. #' @param btn_labels Label(s) for button(s). #' @param btn_colors Color(s) for button(s). #' @param reset_input Set the input value to \code{NULL} when alert is displayed. @@ -383,6 +384,7 @@ inputSweetAlert <- function(session, "email", "url"), inputOptions = NULL, inputPlaceholder = NULL, + inputValidator = NULL, btn_labels = "Ok", btn_colors = NULL, reset_input = TRUE, @@ -407,25 +409,30 @@ inputSweetAlert <- function(session, if (!is.null(inputOptions)) { inputOptions <- choicesWithNames(inputOptions) } + swal <- dropNullsOrNA(list( + title = title, + text = text, + icon = type, + input = input, + inputOptions = inputOptions, + inputPlaceholder = inputPlaceholder, + confirmButtonText = btn_labels[1], + confirmButtonColor = btn_colors[1], + cancelButtonText = btn_labels[2], + cancelButtonColor = btn_colors[2], + showCancelButton = !is.na(btn_labels[2]), + ... + )) + toeval <- unlist(lapply(swal, function(x) { + inherits(x, "AsIs") + })) session$sendCustomMessage( type = "sweetalert-sw-input", message = list( id = inputId, reset_input = reset_input, - swal = dropNullsOrNA(list( - title = title, - text = text, - icon = type, - input = input, - inputOptions = inputOptions, - inputPlaceholder = inputPlaceholder, - confirmButtonText = btn_labels[1], - confirmButtonColor = btn_colors[1], - cancelButtonText = btn_labels[2], - cancelButtonColor = btn_colors[2], - showCancelButton = !is.na(btn_labels[2]), - ... - )) + eval = list1(names(swal)[toeval]), + swal = swal ) ) } diff --git a/examples/sweetalert-input.R b/examples/sweetalert-input.R index d045cf42..099cf3f8 100644 --- a/examples/sweetalert-input.R +++ b/examples/sweetalert-input.R @@ -57,7 +57,14 @@ server <- function(input, output, session) { "myradio", input = "radio", inputOptions = c("Banana" , "Orange", "Apple"), - title = "What's your favorite fruit ?" + title = "What's your favorite fruit ?", + inputValidator = I( + "function(value) { + if (!value) { + return 'You need to choose something!'; + } + }" + ) ) }) output$radio <- renderPrint(input$myradio) diff --git a/inst/assets/sweetalert2/sweetalert-bindings.js b/inst/assets/sweetalert2/sweetalert-bindings.js index ffe019ee..880d8589 100644 --- a/inst/assets/sweetalert2/sweetalert-bindings.js +++ b/inst/assets/sweetalert2/sweetalert-bindings.js @@ -1,5 +1,6 @@ /*jshint - jquery:true + jquery:true, + evil: true */ /*global Swal, CharacterData, DocumentType, Shiny */ @@ -68,6 +69,11 @@ Shiny.addCustomMessageHandler("sweetalert-sw-input", function(data) { if (data.reset_input) { Shiny.setInputValue(data.id, null); } + if (data.eval instanceof Array) { + $.each(data.eval, function (i, x) { + data.swal[x] = eval("(" + data.swal[x][0] + ")"); + }); + } Swal.fire(data.swal).then(function(result) { Shiny.setInputValue(data.id, result.value, { priority: "event" }); }); diff --git a/man/inputSweetAlert.Rd b/man/inputSweetAlert.Rd index 9cf07e63..3e9a9b62 100644 --- a/man/inputSweetAlert.Rd +++ b/man/inputSweetAlert.Rd @@ -14,6 +14,7 @@ inputSweetAlert( "url"), inputOptions = NULL, inputPlaceholder = NULL, + inputValidator = NULL, btn_labels = "Ok", btn_colors = NULL, reset_input = TRUE, @@ -40,6 +41,8 @@ If in a Shiny module, it use same logic than inputs : use namespace in UI, not i \item{inputPlaceholder}{Placeholder for the input, use it for \code{"text"} or \code{"checkbox"}.} +\item{inputValidator}{JavaScript function to validate input. Must be a character wrapped in \code{I()}.} + \item{btn_labels}{Label(s) for button(s).} \item{btn_colors}{Color(s) for button(s).} @@ -114,7 +117,14 @@ server <- function(input, output, session) { "myradio", input = "radio", inputOptions = c("Banana" , "Orange", "Apple"), - title = "What's your favorite fruit ?" + title = "What's your favorite fruit ?", + inputValidator = I( + "function(value) { + if (!value) { + return 'You need to choose something!'; + } + }" + ) ) }) output$radio <- renderPrint(input$myradio) diff --git a/tests/testthat/test-SweetAlert.R b/tests/testthat/test-SweetAlert.R index 9198185f..488c7429 100644 --- a/tests/testthat/test-SweetAlert.R +++ b/tests/testthat/test-SweetAlert.R @@ -128,7 +128,7 @@ test_that("inputSweetAlert", { sendIA_msg <- session$lastCustomMessage$message expect_identical(sendIA_msg$id, "MY_INPUT") - expect_length(sendIA_msg, 3) + expect_length(sendIA_msg, 4) expect_identical(sendIA_msg$swal$title, "TITLE") expect_is(sendIA_msg$swal$text, "json") })