shinyvalidate的add_rule传入命名函数引用响应式参数报错求解
错误原因
调用iv$add_rule("num2", checkRange, value2 = input$num1)时,R会在server函数初始化阶段立即对value2 = input$num1参数求值,而初始化阶段不属于任何响应式消费者上下文,直接读取响应式值input$num1就会触发报错。
匿名函数的场景下,input$num1写在函数内部,shinyvalidate只会在校验触发(用户修改输入后)时才执行该函数,此时运行在shinyvalidate内部的响应式环境中,因此可以正常访问input值。
解决方法
两种方案都可以实现命名函数复用,同时避免提前读取响应式值:
方案1:匿名函数包裹调用
无需修改现有checkRange函数,仅在add_rule中用一层匿名函数包裹调用,保证input$num1在校验执行时才取值:
# 原有checkRange函数无需改动 checkRange <- function(value, value2){ if(value < -2 * value2 || value > 2 * value2 ){ paste0("Please specify a number that is within the range: ", -2 * value2, ":", 2 * value2, " - Thank you!") } } # server中add_rule部分修改为如下写法 iv$add_rule("num2", function(value) { checkRange(value, input$num1) })
方案2:定义高阶校验函数
如果需要大量复用同类校验逻辑,可以定义返回校验函数的高阶函数,直接封装依赖的响应式引用:
# 定义高阶校验函数 checkRange <- function(range_base) { # 返回实际执行的校验函数 function(value) { if(value < -2 * range_base || value > 2 * range_base ){ paste0("Please specify a number that is within the range: ", -2 * range_base, ":", 2 * range_base, " - Thank you!") } } } # server中直接调用高阶函数传入依赖的input值即可 iv$add_rule("num2", checkRange(input$num1))
注:你提供的匿名函数示例存在逻辑笔误,
value > 2 * input$num2应为value > 2 * input$num1,否则校验范围会依赖当前正在输入的num2本身,不符合需求。
内容的提问来源于stack exchange,提问作者marton_l_gy
相关产品推荐
相关产品推荐

