Developer-facing utilities for implementing a custom renderXXX()
function.
Before using these utilities directly, consider using the htmlwidgets
package to implement custom
outputs (i.e., custom renderXXX()
/xxxOutput()
functions). That said,
these utilities can be used more directly if a full-blown htmlwidget isn't
needed and/or the user-supplied reactive expression needs to be wrapped in
additional call(s).
createRenderFunction(
func,
transform = function(value, session, name, ...) value,
outputFunc = NULL,
outputArgs = NULL,
cacheHint = "auto",
cacheWriteHook = NULL,
cacheReadHook = NULL
)
quoToFunction(q, label = sys.call(-1)[[1]], ..stacktraceon = FALSE)
installExprFunction(
expr,
name,
eval.env = parent.frame(2),
quoted = FALSE,
assign.env = parent.frame(1),
label = sys.call(-1)[[1]],
wrappedWithLabel = TRUE,
..stacktraceon = FALSE
)
A function without parameters, that returns user data. If the returned value is a promise, then the render function will proceed in async mode.
A function that takes four arguments: value
,
session
, name
, and ...
(for future-proofing). This
function will be invoked each time a value is returned from func
,
and is responsible for changing the value into a JSON-ready value to be
JSON-encoded and sent to the browser.
The UI function that is used (or most commonly used) with this render function. This can be used in R Markdown documents to create complete output widgets out of just the render function.
A list of arguments to pass to the uiFunc
. Render
functions should include outputArgs = list()
in their own parameter list,
and pass through the value to markRenderFunction
, to allow app authors to
customize outputs. (Currently, this is only supported for dynamically
generated UIs, such as those created by Shiny code snippets embedded in R
Markdown documents).
One of "auto"
, FALSE
, or some other information to
identify this instance for caching using bindCache()
. If "auto"
, it
will try to automatically infer caching information. If FALSE
, do not
allow caching for the object. Some render functions (such as renderPlot)
contain internal state that makes them unsuitable for caching.
Used if the render function is passed to bindCache()
.
This is an optional callback function to invoke before saving the value
from the render function to the cache. This function must accept one
argument, the value returned from renderFunc
, and should return the value
to store in the cache.
Used if the render function is passed to bindCache()
.
This is an optional callback function to invoke after reading a value from
the cache (if there is a cache hit). The function will be passed one
argument, the value retrieved from the cache. This can be useful when some
side effect needs to occur for a render function to behave correctly. For
example, some render functions call createWebDependency()
so that Shiny
is able to serve JS and CSS resources.
Quosure of the expression x
. When capturing expressions to create
your quosure, it is recommended to use rlang::enquo0()
to not unquote
the object too early. See rlang::enquo0()
for more details.
A label for the object to be shown in the debugger. Defaults to the name of the calling function.
A quoted or unquoted expression, or a quosure.
The name the function should be given
The desired environment for the function. Defaults to the calling environment two steps back.
Is the expression quoted?
The environment in which the function should be assigned.
Advanced use only. For stack manipulation purposes; see
stacktrace()
.
An annotated render function, ready to be assigned to an
output
slot.
To implement a custom renderXXX()
function, essentially 2 things are needed:
Capture the user's reactive expression as a function.
New renderXXX()
functions can use quoToFunction()
for this, but
already existing renderXXX()
functions that contain env
and quoted
parameters may want to continue using installExprFunction()
for better
legacy support (see examples).
Flag the resulting function (from 1) as a Shiny rendering function and also provide a UI container for displaying the result of the rendering function.
createRenderFunction()
is currently recommended (instead of
markRenderFunction()
) for this step (see examples).
quoToFunction()
: convert a quosure to a function.
installExprFunction()
: converts a user's reactive expr
into a
function that's assigned to a name
in the assign.env
.
# A custom render function that repeats the supplied value 3 times
renderTriple <- function(expr) {
# Wrap user-supplied reactive expression into a function
func <- quoToFunction(rlang::enquo0(expr))
createRenderFunction(
func,
transform = function(value, session, name, ...) {
paste(rep(value, 3), collapse=", ")
},
outputFunc = textOutput
)
}
# For better legacy support, consider using installExprFunction() over quoToFunction()
renderTripleLegacy <- function(expr, env = parent.frame(), quoted = FALSE) {
func <- installExprFunction(expr, "func", env, quoted)
createRenderFunction(
func,
transform = function(value, session, name, ...) {
paste(rep(value, 3), collapse=", ")
},
outputFunc = textOutput
)
}
# Test render function from the console
reactiveConsole(TRUE)
v <- reactiveVal("basic")
r <- renderTriple({ v() })
r()
#> [1] "basic, basic, basic"
#> [1] "basic, basic, basic"
# User can supply quoted code via rlang::quo(). Note that evaluation of the
# expression happens when r2() is invoked, not when r2 is created.
q <- rlang::quo({ v() })
r2 <- rlang::inject(renderTriple(!!q))
v("rlang")
r2()
#> [1] "rlang, rlang, rlang"
#> [1] "rlang, rlang, rlang"
# Supplying quoted code without rlang::quo() requires installExprFunction()
expr <- quote({ v() })
r3 <- renderTripleLegacy(expr, quoted = TRUE)
v("legacy")
r3()
#> [1] "legacy, legacy, legacy"
#> [1] "legacy, legacy, legacy"
# The legacy approach also supports with quosures (env is ignored in this case)
q <- rlang::quo({ v() })
r4 <- renderTripleLegacy(q, quoted = TRUE)
v("legacy-rlang")
r4()
#> [1] "legacy-rlang, legacy-rlang, legacy-rlang"
#> [1] "legacy-rlang, legacy-rlang, legacy-rlang"
# Turn off reactivity in the console
reactiveConsole(FALSE)