shinyvalidate — использование реактивного выражения в add_rule()

#r #shiny #shiny-reactivity

Вопрос:

Я пытаюсь реализовать отзывы пользователей для приложения, над которым работаю, используя пакет shinyvalidate. Некоторые отзывы, которые я хочу сообщить пользователю, касаются того, находится ли выбранное им значение в определенном диапазоне или нет. Диапазон интересов зависит от другого вклада, который они внесли (я включил упрощенное повторение кода).

Таким образом, будет ли выполнено предварительное условие, представляющее интерес, зависит от реактивного значения. Сначала я определяю функцию, которая проверяет, находится ли предоставленное значение в указанном диапазоне. Затем я вызываю эту функцию в add_rule (), используя reactive в качестве аргумента функции. Это приводит к ошибке, в которой говорится, что я не могу получить доступ к реактивному с помощью add_rule. Предположительно, это так, потому что объект InputValidator не является реактивным потребителем.

Сообщение об ошибке:

 Warning: Error in Can't access reactive value 'num1' outside of reactive consumer.
i Do you need to wrap inside reactive() or observer()?
  55: <Anonymous>
Error: Can't access reactive value 'num1' outside of reactive consumer.
i Do you need to wrap inside reactive() or observer()?
 

Однако, если я использую неназванную функцию в add_rule(), я могу указать диапазон, который зависит от реакции, и я больше не получу сообщение об ошибке. Безымянные и именованные функции, которые я использую, идентичны, и я не понимаю, почему я получаю сообщение об ошибке при использовании именованной функции, но я не получаю сообщение об ошибке при использовании именованной функции.

Вот мой код, использующий именованную функцию:

 library(shiny)
library(shinyvalidate)
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, " - Tank you!")
  }
}

ui <- fluidPage(
  fluidRow(
           numericInput("num1",
                        "Please specify your first number",
                        value = NULL),
           numericInput("num2",
                        "Please specify a different number",
                        value = NULL),
           verbatimTextOutput("selectedNums")
  
)
)

server <- function(input, output, session){
  iv <- InputValidator$new()
  iv$add_rule("num1", sv_required())
  iv$add_rule("num2", sv_required())
  iv$add_rule("num2", checkRange, value2 = input$num1)
  iv$enable()
  output$selectedNums <- renderPrint({
    req(iv$is_valid())
    paste0("The first number = ", input$num1, " and the second number = ", input$num2)
  })
}

app <- shinyApp(ui, server)

runApp(app)
 

And here is the code using an anonymous function (UI and server code are largely identical except one call to iv$add_rule()):

 library(shiny)
library(shinyvalidate)
ui <- fluidPage(
  fluidRow(
           numericInput("num1",
                        "Please specify your first number",
                        value = NULL),
           numericInput("num2",
                        "Please specify a different number",
                        value = NULL),
           verbatimTextOutput("selectedNums")
  
)
)

server <- function(input, output, session){
  iv <- InputValidator$new()
  iv$add_rule("num1", sv_required())
  iv$add_rule("num2", sv_required())
  iv$add_rule("num2", function(value){
    if(value < - 2 * input$num1 || value > 2 * input$num2){
      paste0("Please specify a number that is within the range: ", -2 * input$num1, ":", 2 * input$num1, " - Tank you!")
    }
  })
  iv$enable()
  output$selectedNums <- renderPrint({
    req(iv$is_valid())
    paste0("The first number = ", input$num1, " and the second number = ", input$num2)
  })
}

app <- shinyApp(ui, server)

runApp(app)
 

Я бы предпочел использовать именованную функцию, так как хотел бы повторно использовать код несколько раз. Может ли кто-нибудь помочь мне понять, почему я получаю сообщение об ошибке с именованной функцией, но не с безымянной?

Ответ №1:

Вы могли бы сделать:

   iv$add_rule("num2", function(value){checkRange(value, input$num1)})
 

Комментарии:

1. Большое спасибо! Не могли бы вы указать мне на какой-нибудь ресурс, который мог бы помочь мне понять, почему этот код работает? Я просто сбит с толку и не знаю, чего мне не хватает.