Event handler — observeEvent
R/reactives.R
Description
Respond to "event-like" reactive inputs, values, and expressions. As of Shiny
1.6.0, we recommend using bindEvent()
instead of eventReactive()
and
observeEvent()
. This is because bindEvent()
can be composed with
bindCache()
, and because it can also be used with render
functions (like
renderText()
and renderPlot()
).
observeEvent(
eventExpr,
handlerExpr,
event.env = parent.frame(),
event.quoted = FALSE,
handler.env = parent.frame(),
handler.quoted = FALSE,
...,
label = NULL,
suspended = FALSE,
priority = 0,
domain = getDefaultReactiveDomain(),
autoDestroy = TRUE,
ignoreNULL = TRUE,
ignoreInit = FALSE,
once = FALSE
)
eventReactive(
eventExpr,
valueExpr,
event.env = parent.frame(),
event.quoted = FALSE,
value.env = parent.frame(),
value.quoted = FALSE,
...,
label = NULL,
domain = getDefaultReactiveDomain(),
ignoreNULL = TRUE,
ignoreInit = FALSE
)
Arguments
- eventExpr
A (quoted or unquoted) expression that represents the event; this can be a simple reactive value like
input$click
, a call to a reactive expression likedataset()
, or even a complex expression inside curly braces- handlerExpr
The expression to call whenever
eventExpr
is invalidated. This should be a side-effect-producing action (the return value will be ignored). It will be executed within anisolate()
scope.- event.env
The parent environment for the reactive expression. By default, this is the calling environment, the same as when defining an ordinary non-reactive expression. If
eventExpr
is a quosure andevent.quoted
isTRUE
, thenevent.env
is ignored.- event.quoted
If it is
TRUE
, then thequote()
ed value ofeventExpr
will be used wheneventExpr
is evaluated. IfeventExpr
is a quosure and you would like to use its expression as a value foreventExpr
, then you must setevent.quoted
toTRUE
.- handler.env
The parent environment for the reactive expression. By default, this is the calling environment, the same as when defining an ordinary non-reactive expression. If
handlerExpr
is a quosure andhandler.quoted
isTRUE
, thenhandler.env
is ignored.- handler.quoted
If it is
TRUE
, then thequote()
ed value ofhandlerExpr
will be used whenhandlerExpr
is evaluated. IfhandlerExpr
is a quosure and you would like to use its expression as a value forhandlerExpr
, then you must sethandler.quoted
toTRUE
.- ...
Currently not used.
- label
A label for the observer or reactive, useful for debugging.
- suspended
If
TRUE
, start the observer in a suspended state. IfFALSE
(the default), start in a non-suspended state.- priority
An integer or numeric that controls the priority with which this observer should be executed. An observer with a given priority level will always execute sooner than all observers with a lower priority level. Positive, negative, and zero values are allowed.
- domain
See domains.
- autoDestroy
If
TRUE
(the default), the observer will be automatically destroyed when its domain (if any) ends.- ignoreNULL
Whether the action should be triggered (or value calculated, in the case of
eventReactive
) when the input isNULL
. See Details.- ignoreInit
If
TRUE
, then, when thisobserveEvent
is first created/initialized, ignore thehandlerExpr
(the second argument), whether it is otherwise supposed to run or not. The default isFALSE
. See Details.- once
Whether this
observeEvent
should be immediately destroyed after the first time that the code inhandlerExpr
is run. This pattern is useful when you want to subscribe to a event that should only happen once.- valueExpr
The expression that produces the return value of the
eventReactive
. It will be executed within anisolate()
scope.- value.env
The parent environment for the reactive expression. By default, this is the calling environment, the same as when defining an ordinary non-reactive expression. If
valueExpr
is a quosure andvalue.quoted
isTRUE
, thenvalue.env
is ignored.- value.quoted
If it is
TRUE
, then thequote()
ed value ofvalueExpr
will be used whenvalueExpr
is evaluated. IfvalueExpr
is a quosure and you would like to use its expression as a value forvalueExpr
, then you must setvalue.quoted
toTRUE
.
Value
observeEvent
returns an observer reference class object (see
observe()
). eventReactive
returns a reactive expression
object (see reactive()
).
Details
Shiny's reactive programming framework is primarily designed for calculated
values (reactive expressions) and side-effect-causing actions (observers)
that respond to any of their inputs changing. That's often what is
desired in Shiny apps, but not always: sometimes you want to wait for a
specific action to be taken from the user, like clicking an
actionButton()
, before calculating an expression or taking an
action. A reactive value or expression that is used to trigger other
calculations in this way is called an event.
These situations demand a more imperative, "event handling" style of
programming that is possible--but not particularly intuitive--using the
reactive programming primitives observe()
and
isolate()
. observeEvent
and eventReactive
provide
straightforward APIs for event handling that wrap observe
and
isolate
.
Use observeEvent
whenever you want to perform an action in
response to an event. (Note that "recalculate a value" does not generally
count as performing an action--see eventReactive
for that.) The first
argument is the event you want to respond to, and the second argument is a
function that should be called whenever the event occurs. Note that
observeEvent()
is equivalent to using observe() %>% bindEvent()
and as of
Shiny 1.6.0, we recommend the latter.
Use eventReactive
to create a calculated value that only
updates in response to an event. This is just like a normal
reactive expression except it ignores all the usual
invalidations that come from its reactive dependencies; it only invalidates
in response to the given event. Note that
eventReactive()
is equivalent to using reactive() %>% bindEvent()
and as of
Shiny 1.6.0, we recommend the latter.
ignoreNULL and ignoreInit
Both observeEvent
and eventReactive
take an ignoreNULL
parameter that affects behavior when the eventExpr
evaluates to
NULL
(or in the special case of an actionButton()
,
0
). In these cases, if ignoreNULL
is TRUE
, then an
observeEvent
will not execute and an eventReactive
will raise a
silent validation error. This is useful behavior if you
don't want to do the action or calculation when your app first starts, but
wait for the user to initiate the action first (like a "Submit" button);
whereas ignoreNULL=FALSE
is desirable if you want to initially perform
the action/calculation and just let the user re-initiate it (like a
"Recalculate" button).
Likewise, both observeEvent
and eventReactive
also take in an
ignoreInit
argument. By default, both of these will run right when they
are created (except if, at that moment, eventExpr
evaluates to NULL
and ignoreNULL
is TRUE
). But when responding to a click of an action
button, it may often be useful to set ignoreInit
to TRUE
. For
example, if you're setting up an observeEvent
for a dynamically created
button, then ignoreInit = TRUE
will guarantee that the action (in
handlerExpr
) will only be triggered when the button is actually clicked,
instead of also being triggered when it is created/initialized. Similarly,
if you're setting up an eventReactive
that responds to a dynamically
created button used to refresh some data (then returned by that eventReactive
),
then you should use eventReactive([...], ignoreInit = TRUE)
if you want
to let the user decide if/when they want to refresh the data (since, depending
on the app, this may be a computationally expensive operation).
Even though ignoreNULL
and ignoreInit
can be used for similar
purposes they are independent from one another. Here's the result of combining
these:
ignoreNULL = TRUE
andignoreInit = FALSE
This is the default. This combination means that
handlerExpr
/valueExpr
will run every time thateventExpr
is notNULL
. If, at the time of the creation of theobserveEvent
/eventReactive
,eventExpr
happens to not beNULL
, then the code runs.ignoreNULL = FALSE
andignoreInit = FALSE
This combination means that
handlerExpr
/valueExpr
will run every time no matter what.ignoreNULL = FALSE
andignoreInit = TRUE
This combination means that
handlerExpr
/valueExpr
will not run when theobserveEvent
/eventReactive
is created (becauseignoreInit = TRUE
), but it will run every other time.ignoreNULL = TRUE
andignoreInit = TRUE
This combination means that
handlerExpr
/valueExpr
will not run when theobserveEvent
/eventReactive
is created (becauseignoreInit = TRUE
). After that,handlerExpr
/valueExpr
will run every time thateventExpr
is notNULL
.
See also
Examples
## Only run examples in interactive R sessions
if (interactive()) {
## App 1: Sample usage
shinyApp(
ui = fluidPage(
column(4,
numericInput("x", "Value", 5),
br(),
actionButton("button", "Show")
),
column(8, tableOutput("table"))
),
server = function(input, output) {
# Take an action every time button is pressed;
# here, we just print a message to the console
observeEvent(input$button, {
cat("Showing", input$x, "rows\n")
})
# The observeEvent() above is equivalent to:
# observe({
# cat("Showing", input$x, "rows\n")
# }) %>%
# bindEvent(input$button)
# Take a reactive dependency on input$button, but
# not on any of the stuff inside the function
df <- eventReactive(input$button, {
head(cars, input$x)
})
output$table <- renderTable({
df()
})
}
)
## App 2: Using `once`
shinyApp(
ui = basicPage( actionButton("go", "Go")),
server = function(input, output, session) {
observeEvent(input$go, {
print(paste("This will only be printed once; all",
"subsequent button clicks won't do anything"))
}, once = TRUE)
# The observeEvent() above is equivalent to:
# observe({
# print(paste("This will only be printed once; all",
# "subsequent button clicks won't do anything"))
# }) %>%
# bindEvent(input$go, once = TRUE)
}
)
## App 3: Using `ignoreInit` and `once`
shinyApp(
ui = basicPage(actionButton("go", "Go")),
server = function(input, output, session) {
observeEvent(input$go, {
insertUI("#go", "afterEnd",
actionButton("dynamic", "click to remove"))
# set up an observer that depends on the dynamic
# input, so that it doesn't run when the input is
# created, and only runs once after that (since
# the side effect is remove the input from the DOM)
observeEvent(input$dynamic, {
removeUI("#dynamic")
}, ignoreInit = TRUE, once = TRUE)
})
}
)
}