Create a reactive value that can be updated imperatively (like a
shiny::reactiveVal()
) but whose state is ultimately governed by a reactive
validation expression. This ensures that its value is always consistent with
its reactive dependencies before any downstream dependents are re-evaluated.
Usage
validated_reactive_val(
validation_expr,
value = NULL,
default = NULL,
label = NULL,
env = rlang::caller_env()
)
# S3 method for class 'vrv'
x$name
Arguments
- validation_expr
(
expression
) A reactive expression that defines the authoritative state of thisvalidated_reactive_value
, This expression can access thevalidated_reactive_value
's own current value via the.vrv()
pronoun to reconcile it with upstream dependencies.- value
(various) The initial value. This value will be coerced via the validation expression when accessed. If this value is reactive, an observer with
priority = Inf
will be created to attempt to keep the validated value in sync with that reactive.- default
(various, including
expression
orreactive expression
) A value to use when the current value is not valid according to the defined rules. Defaults toNULL
.- label
(length-1
character
orNULL
) An optional label for thevalidated_reactive_value
, used for debugging.- env
(
environment
) The environment in which to evaluate thevalidation_expr
.- x
(
vrv
) Avrv
object.- name
(length-1
character
) The name of the helper function to access. Expects one ofvalue
,error
, oris_default
. Other values returnNULL
.
Value
A vrv
object, which is a function with a custom class. Call it
with no arguments to (reactively) read the validated value. Call it with a
single argument to imperatively set the value; it will be automatically
validated on the next read. You can also access the most recent validation
error with my_vrv$error()
and check if the current value is the default
with my_vrv$is_default()
.
Examples
if (FALSE) { # interactive()
library(shiny)
ui <- fluidPage( selectInput("level", "Level", choices = c("A", "B")),
uiOutput("group_ui"), textOutput("current_group") )
server <- function(input, output, session) {
# `group_val` depends on `input$level` and can also be set by `input$group`.
group_val <- validated_reactive_val(
value = "A1",
validation_expr = {
# If the current value is not valid for the new level, reset it.
valid_groups <- if (input$level == "A") {
c("A1", "A2")
} else {
c("B1", "B2")
}
if (.vrv() %in% valid_groups) {
.vrv()
} else {
valid_groups[[1]]
}
}
)
# When the user changes the group input, imperatively update the vrv.
observeEvent(input$group, {
group_val(input$group)
})
# The UI for the group dropdown is dynamic.
output$group_ui <- renderUI({
choices <- if (input$level == "A") c("A1", "A2") else c("B1", "B2")
selectInput("group", "Group", choices = choices, selected = group_val())
})
output$current_group <- renderText({
paste("Current Validated Group:", group_val())
})
}
shinyApp(ui, server)
}