mirror of
https://github.com/rstudio/shiny.git
synced 2026-04-07 03:00:20 -04:00
Add req function for validating required inputs/values
This commit is contained in:
@@ -153,6 +153,7 @@ export(renderTable)
|
||||
export(renderText)
|
||||
export(renderUI)
|
||||
export(repeatable)
|
||||
export(req)
|
||||
export(runApp)
|
||||
export(runExample)
|
||||
export(runGist)
|
||||
|
||||
5
NEWS
5
NEWS
@@ -50,6 +50,11 @@ shiny 0.12.2.9000
|
||||
* Fixed #1018: the selected value of a selectize input is guaranteed to be
|
||||
selected in server-side mode.
|
||||
|
||||
* Added `req` function, which provides a simple way to prevent a reactive,
|
||||
observer, or output from executing until all required inputs and values are
|
||||
available. (Similar functionality has been available for a while using
|
||||
validate/need, but req provides a much simpler and more direct interface.)
|
||||
|
||||
shiny 0.12.2
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
86
R/utils.R
86
R/utils.R
@@ -980,6 +980,92 @@ need <- function(expr, message = paste(label, "must be provided"), label) {
|
||||
return(invisible(NULL))
|
||||
}
|
||||
|
||||
#' Check for required values
|
||||
#'
|
||||
#' Ensure that values are available ("truthy"--see Details) before proceeding
|
||||
#' with a calculation or action. If any of the given values is not truthy, the
|
||||
#' operation is stopped by raising a "silent" exception (not logged by Shiny,
|
||||
#' nor displayed in the Shiny app's UI).
|
||||
#'
|
||||
#' The \code{req} function was designed to be used in one of two ways. The first
|
||||
#' is to call it like a statement (ignoring its return value) before attempting
|
||||
#' operations using the required values:
|
||||
#'
|
||||
#' \preformatted{rv <- reactiveValues(state = FALSE)
|
||||
#' r <- reactive({
|
||||
#' req(input$a, input$b, rv$state)
|
||||
#' # Code that uses input$a, input$b, and/or rv$state...
|
||||
#' })}
|
||||
#'
|
||||
#' In this example, if \code{r()} is called and any of \code{input$a},
|
||||
#' \code{input$b}, and \code{rv$state} are \code{NULL}, \code{FALSE}, \code{""},
|
||||
#' etc., then the \code{req} call will trigger an error that propagates all the
|
||||
#' way up to whatever render block or observer is executing.
|
||||
#'
|
||||
#' The second is to use it to wrap an expression that must be truthy:
|
||||
#'
|
||||
#' \preformatted{output$plot <- renderPlot({
|
||||
#' if (req(input$plotType) == "histogram") {
|
||||
#' hist(dataset())
|
||||
#' } else if (input$plotType == "scatter") {
|
||||
#' qplot(dataset(), aes(x = x, y = y))
|
||||
#' }
|
||||
#' })}
|
||||
#'
|
||||
#' In this example, \code{req(input$plotType)} first checks that
|
||||
#' \code{input$plotType} is truthy, and if so, returns it. This is a convenient
|
||||
#' way to check for a value "inline" with its first use.
|
||||
#'
|
||||
#' \strong{Truthy and falsy values}
|
||||
#'
|
||||
#' The terms "truthy" and "falsy" generally indicate whether a value, when
|
||||
#' coerced to a \code{\link{logical}}, is \code{TRUE} or \code{FALSE}. We use
|
||||
#' the term a little loosely here; our usage tries to match the intuitive
|
||||
#' notions of "Is this value missing or available?", or "Has the user provided
|
||||
#' an answer?", or in the case of action buttons, "Has the button been
|
||||
#' clicked?".
|
||||
#'
|
||||
#' For example, a \code{textInput} that has not been filled out by the user has
|
||||
#' a value of \code{""}, so that is considered a falsy value.
|
||||
#'
|
||||
#' To be precise, \code{req} considers a value truthy \emph{unless} it is one
|
||||
#' of:
|
||||
#'
|
||||
#' \itemize{
|
||||
#' \item{\code{FALSE}}
|
||||
#' \item{\code{NULL}}
|
||||
#' \item{\code{""}}
|
||||
#' \item{An empty atomic vector}
|
||||
#' \item{An atomic vector that contains only missing values}
|
||||
#' \item{A logical vector that contains all \code{FALSE} or missing values}
|
||||
#' \item{An object of class \code{"try-error"}}
|
||||
#' \item{A value that represents an unclicked \code{\link{actionButton}}}
|
||||
#' }
|
||||
#'
|
||||
#' Note in particular that the value \code{0} is considered truthy, even though
|
||||
#' \code{as.logical(0)} is \code{FALSE}.
|
||||
#'
|
||||
#' If the built-in rules for truthiness do not match your requirements, you can
|
||||
#' always work around them. Since \code{FALSE} is falsy, you can simply provide
|
||||
#' the results of your own checks to \code{req}:
|
||||
#'
|
||||
#' \code{req(input$a != 0)}
|
||||
#'
|
||||
#' @param ... Values to check for truthiness.
|
||||
#' @return The first value that was passed in.
|
||||
#'
|
||||
#' @export
|
||||
req <- function(...) {
|
||||
for (item in list(...)) {
|
||||
if (!isTruthy(item))
|
||||
stopWithCondition("validation", "")
|
||||
}
|
||||
if (length(list(...)) > 0)
|
||||
..1
|
||||
else
|
||||
invisible()
|
||||
}
|
||||
|
||||
isTruthy <- function(x) {
|
||||
if (inherits(x, 'try-error'))
|
||||
return(FALSE)
|
||||
|
||||
@@ -147,6 +147,7 @@ sd_section("Extending Shiny",
|
||||
sd_section("Utility functions",
|
||||
"Miscellaneous utilities that may be useful to advanced users or when extending Shiny.",
|
||||
c(
|
||||
"req",
|
||||
"validate",
|
||||
"session",
|
||||
"exprToFunction",
|
||||
|
||||
@@ -89,6 +89,18 @@ test_that("need() works as expected", {
|
||||
expect_null(need(c(FALSE, FALSE, TRUE), FALSE))
|
||||
})
|
||||
|
||||
test_that("req works", {
|
||||
expect_error(req(TRUE, FALSE))
|
||||
expect_error(req(TRUE, stop("boom")))
|
||||
expect_equivalent(req(1, TRUE), 1)
|
||||
|
||||
# All req arguments are evaluated before any are tested for truthiness. This
|
||||
# isn't necessary a good property, but let's at least document it with a test.
|
||||
value <- 0
|
||||
expect_error(req(NULL, value <- 1))
|
||||
expect_equal(value, 1)
|
||||
})
|
||||
|
||||
test_that("anyUnnamed works as expected", {
|
||||
expect_false(anyUnnamed(list()))
|
||||
expect_true(anyUnnamed(list(1,2,3)))
|
||||
|
||||
86
man/req.Rd
Normal file
86
man/req.Rd
Normal file
@@ -0,0 +1,86 @@
|
||||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/utils.R
|
||||
\name{req}
|
||||
\alias{req}
|
||||
\title{Check for required values}
|
||||
\usage{
|
||||
req(...)
|
||||
}
|
||||
\arguments{
|
||||
\item{...}{Values to check for truthiness.}
|
||||
}
|
||||
\value{
|
||||
The first value that was passed in.
|
||||
}
|
||||
\description{
|
||||
Ensure that values are available ("truthy"--see Details) before proceeding
|
||||
with a calculation or action. If any of the given values is not truthy, the
|
||||
operation is stopped by raising a "silent" exception (not logged by Shiny,
|
||||
nor displayed in the Shiny app's UI).
|
||||
}
|
||||
\details{
|
||||
The \code{req} function was designed to be used in one of two ways. The first
|
||||
is to call it like a statement (ignoring its return value) before attempting
|
||||
operations using the required values:
|
||||
|
||||
\preformatted{rv <- reactiveValues(state = FALSE)
|
||||
r <- reactive({
|
||||
req(input$a, input$b, rv$state)
|
||||
# Code that uses input$a, input$b, and/or rv$state...
|
||||
})}
|
||||
|
||||
In this example, if \code{r()} is called and any of \code{input$a},
|
||||
\code{input$b}, and \code{rv$state} are \code{NULL}, \code{FALSE}, \code{""},
|
||||
etc., then the \code{req} call will trigger an error that propagates all the
|
||||
way up to whatever render block or observer is executing.
|
||||
|
||||
The second is to use it to wrap an expression that must be truthy:
|
||||
|
||||
\preformatted{output$plot <- renderPlot({
|
||||
if (req(input$plotType) == "histogram") {
|
||||
hist(dataset())
|
||||
} else if (input$plotType == "scatter") {
|
||||
qplot(dataset(), aes(x = x, y = y))
|
||||
}
|
||||
})}
|
||||
|
||||
In this example, \code{req(input$plotType)} first checks that
|
||||
\code{input$plotType} is truthy, and if so, returns it. This is a convenient
|
||||
way to check for a value "inline" with its first use.
|
||||
|
||||
\strong{Truthy and falsy values}
|
||||
|
||||
The terms "truthy" and "falsy" generally indicate whether a value, when
|
||||
coerced to a \code{\link{logical}}, is \code{TRUE} or \code{FALSE}. We use
|
||||
the term a little loosely here; our usage tries to match the intuitive
|
||||
notions of "Is this value missing or available?", or "Has the user provided
|
||||
an answer?", or in the case of action buttons, "Has the button been
|
||||
clicked?".
|
||||
|
||||
For example, a \code{textInput} that has not been filled out by the user has
|
||||
a value of \code{""}, so that is considered a falsy value.
|
||||
|
||||
To be precise, \code{req} considers a value truthy \emph{unless} it is one
|
||||
of:
|
||||
|
||||
\itemize{
|
||||
\item{\code{FALSE}}
|
||||
\item{\code{NULL}}
|
||||
\item{\code{""}}
|
||||
\item{An empty atomic vector}
|
||||
\item{An atomic vector that contains only missing values}
|
||||
\item{A logical vector that contains all \code{FALSE} or missing values}
|
||||
\item{An object of class \code{"try-error"}}
|
||||
\item{A value that represents an unclicked \code{\link{actionButton}}}
|
||||
}
|
||||
|
||||
Note in particular that the value \code{0} is considered truthy, even though
|
||||
\code{as.logical(0)} is \code{FALSE}.
|
||||
|
||||
If the built-in rules for truthiness do not match your requirements, you can
|
||||
always work around them. Since \code{FALSE} is falsy, you can simply provide
|
||||
the results of your own checks to \code{req}:
|
||||
|
||||
\code{req(input$a != 0)}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user