mirror of
https://github.com/rstudio/shiny.git
synced 2026-04-07 03:00:20 -04:00
Features for easier explaining of reactivity
- makeReactiveBinding: Turns a "regular" variable into a reactive. No need to use reactiveValues() for simple reactivity. - setAutoflush (not exported): Causes flushReact() to be called each time something is executed at the R console top-level. - options(shiny.suppressMissingContextError=TRUE): Prevents the "Operation not allowed without an active reactive context" error when attempting to read a reactive value or expression from the console.
This commit is contained in:
@@ -69,6 +69,7 @@ export(is.reactive)
|
||||
export(is.reactivevalues)
|
||||
export(isolate)
|
||||
export(mainPanel)
|
||||
export(makeReactiveBinding)
|
||||
export(navbarPage)
|
||||
export(numericInput)
|
||||
export(observe)
|
||||
|
||||
5
NEWS
5
NEWS
@@ -39,6 +39,11 @@ shiny 0.8.0.99
|
||||
* Added `icon()` function for embedding icons from the
|
||||
[http://fontawesome.io/](font awesome) icon library
|
||||
|
||||
* Added `makeReactiveBinding` function to turn a "regular" variable into a
|
||||
reactive one (i.e. reading the variable makes the current reactive context
|
||||
dependent on it, and setting the variable is a source of reactivity).
|
||||
|
||||
|
||||
shiny 0.8.0
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
||||
20
R/react.R
20
R/react.R
@@ -91,9 +91,13 @@ ReactiveEnvironment <- setRefClass(
|
||||
},
|
||||
currentContext = function() {
|
||||
if (is.null(.currentContext)) {
|
||||
stop('Operation not allowed without an active reactive context. ',
|
||||
'(You tried to do something that can only be done from inside a ',
|
||||
'reactive function.)')
|
||||
if (isTRUE(getOption('shiny.suppressMissingContextError', FALSE))) {
|
||||
return(getDummyContext())
|
||||
} else {
|
||||
stop('Operation not allowed without an active reactive context. ',
|
||||
'(You tried to do something that can only be done from inside a ',
|
||||
'reactive expression or observer.)')
|
||||
}
|
||||
}
|
||||
return(.currentContext)
|
||||
},
|
||||
@@ -135,3 +139,13 @@ flushReact <- function() {
|
||||
getCurrentContext <- function() {
|
||||
.getReactiveEnvironment()$currentContext()
|
||||
}
|
||||
|
||||
getDummyContext <- function() {}
|
||||
local({
|
||||
dummyContext <- NULL
|
||||
getDummyContext <<- function() {
|
||||
if (is.null(dummyContext))
|
||||
dummyContext <<- Context$new('[none]', type='isolate')
|
||||
return(dummyContext)
|
||||
}
|
||||
})
|
||||
|
||||
@@ -626,6 +626,78 @@ observe <- function(x, env=parent.frame(), quoted=FALSE, label=NULL,
|
||||
invisible(o)
|
||||
}
|
||||
|
||||
#' Make a reactive variable
|
||||
#'
|
||||
#' Turns a normal variable into a reactive variable, that is, one that has
|
||||
#' reactive semantics when assigned or read in the usual ways. The variable may
|
||||
#' already exist; if so, its value will be used as the initial value of the
|
||||
#' reactive variable (or \code{NULL} if the variable did not exist).
|
||||
#'
|
||||
#' @param symbol A character string indicating the name of the variable that
|
||||
#' should be made reactive
|
||||
#' @param env The environment that will contain the reactive variable
|
||||
#'
|
||||
#' @return None.
|
||||
#'
|
||||
#' @examples
|
||||
#' \dontrun{
|
||||
#' a <- 10
|
||||
#' makeReactiveBinding("a")
|
||||
#' b <- reactive(a * -1)
|
||||
#' observe(print(b))
|
||||
#' a <- 20
|
||||
#' }
|
||||
#' @export
|
||||
makeReactiveBinding <- function(symbol, env = parent.frame()) {
|
||||
if (exists(symbol, where = env)) {
|
||||
initialValue <- get(symbol, pos = env)
|
||||
do.call(rm, list(symbol, pos = env))
|
||||
}
|
||||
else
|
||||
initialValue <- NULL
|
||||
values <- reactiveValues(value = initialValue)
|
||||
makeActiveBinding(symbol, env=env, fun=function(v) {
|
||||
if (missing(v))
|
||||
values$value
|
||||
else
|
||||
values$value <- v
|
||||
})
|
||||
|
||||
invisible()
|
||||
}
|
||||
|
||||
# `%<-reactive%` <- function(name, value) {
|
||||
# sym <- deparse(substitute(name))
|
||||
# assign(sym, value, pos = parent.frame())
|
||||
# makeReactiveBinding(sym, env=parent.frame())
|
||||
# invisible(NULL)
|
||||
# }
|
||||
|
||||
# Causes flushReact to be called every time an expression is
|
||||
# entered into the top-level prompt
|
||||
setAutoflush <- function(enable) {}
|
||||
local({
|
||||
callbackId <- NULL
|
||||
|
||||
setAutoflush <<- function(enable) {
|
||||
if (identical(is.null(callbackId), !isTRUE(enable))) {
|
||||
return(invisible())
|
||||
}
|
||||
|
||||
if (isTRUE(enable)) {
|
||||
callbackId <<- addTaskCallback(function(expr, value, ok, visible) {
|
||||
timerCallbacks$executeElapsed()
|
||||
flushReact()
|
||||
return(TRUE)
|
||||
})
|
||||
} else {
|
||||
removeTaskCallback(callbackId)
|
||||
callbackId <<- NULL
|
||||
}
|
||||
invisible()
|
||||
}
|
||||
})
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
#' Timer
|
||||
|
||||
34
man/makeReactiveBinding.Rd
Normal file
34
man/makeReactiveBinding.Rd
Normal file
@@ -0,0 +1,34 @@
|
||||
\name{makeReactiveBinding}
|
||||
\alias{makeReactiveBinding}
|
||||
\title{Make a reactive variable}
|
||||
\usage{
|
||||
makeReactiveBinding(symbol, env = parent.frame())
|
||||
}
|
||||
\arguments{
|
||||
\item{symbol}{A character string indicating the name of
|
||||
the variable that should be made reactive}
|
||||
|
||||
\item{env}{The environment that will contain the reactive
|
||||
variable}
|
||||
}
|
||||
\value{
|
||||
None.
|
||||
}
|
||||
\description{
|
||||
Turns a normal variable into a reactive variable, that
|
||||
is, one that has reactive semantics when assigned or read
|
||||
in the usual ways. The variable may already exist; if so,
|
||||
its value will be used as the initial value of the
|
||||
reactive variable (or \code{NULL} if the variable did not
|
||||
exist).
|
||||
}
|
||||
\examples{
|
||||
\dontrun{
|
||||
a <- 10
|
||||
makeReactiveBinding("a")
|
||||
b <- reactive(a * -1)
|
||||
observe(print(b))
|
||||
a <- 20
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user