有光泽的selectInput取决于已验证的反应式不会传递验证错误

ben*_*dae 6 validation r shiny

我试图validate在R Shiny中使用,以防止在不应该显示输出时显示它们。当reactiveinput内部创建验证时使用验证,uiOutput并且验证引发错误时,该错误不会传递给依赖项reactiveoutput

阅读https://shiny.rstudio.com/articles/validation.html并使用时reactlog,我认为问题出在生成的内容上,input而不取决于经过验证的反应性。该文章指出:

闪亮的将:将验证错误传递给依赖它的任何反应式表达式或观察者对象

我不确定真正input内部是uiOutput 什么,但我怀疑它既不是反应性表达也不是观察者。

考虑以下示例:

library(shiny)
library(data.table)

cars <- data.table(mtcars, keep.rownames = T )
setnames(cars, "rn", "name")

ui <- fluidPage(
  selectInput("cyl", "Cyl", c(4, 12)),
  uiOutput("uiOutCars"),
  h4("Filtered Table"),
  tableOutput("filteredTable")
)

server <- function(input, output, session) {

  availableCars <- reactive({
    choices <- cars[cyl == input$cyl, name]
    validate(need(try(length(choices) > 0),
                  "No cars with this cyl!"))
    choices

  })


  output$uiOutCars <- renderUI({
    selectInput(inputId = "selectCar", 
                label = "Car", 
                choices = availableCars())
  })


  output$filteredTable <- renderTable({
    cars[name == input$selectCar]
  })


}

shinyApp(ui, server)
Run Code Online (Sandbox Code Playgroud)

初始状态:

闪亮的应用初始状态

当将cyl输入从4 更改为12时(中没有12个汽缸的汽车cars),selectCar则不会显示输入。验证消息No cars with this cyl!为:

闪亮的应用程序输入柱面更改为12

我的期望是,filteredTableinput$selectCar 应该停止显示,因为应该没有适当的值。但是,当availableCars()尚未引发错误时,它似乎保留了其最后一个值。

是否可以“通过”传递input由a生成的验证错误uiOutput

编辑

@TimTeaFan补充说,使用时也不起作用updateSelectInput(感谢检查!):

library(shiny)
library(data.table)

cars <- data.table(mtcars, keep.rownames = T )
setnames(cars, "rn", "name")

ui <- fluidPage(
    selectInput("cyl", "Cyl", c(4, 
    selectInput("selectCar", "Car", 
                cars[cyl == 4, name]), # differs from original example here
    h4("Filtered Table"),
    tableOutput("filteredTable")
)

server <- function(input, output, session) {

    availableCars <- reactive({
        choices <- cars[cyl == input$cyl, name]
        validate(need(length(choices) > 0,
                      "No cars with this cyl!"))
        choices

    })

    # differs from original example here
    observeEvent(input$cyl, {
        updateSelectInput(session, "selectCar",
                          choices = availableCars())
    })


    output$filteredTable <- renderTable({
        cars[name == input$selectCar]
    })


}

shinyApp(ui, server)
Run Code Online (Sandbox Code Playgroud)

Mar*_*cus 2

为了完整起见,根据我对其他答案的评论,严格来说,您不能将验证消息传播到输入(输入uiOutput或其他输入)。正如文章中引用的那样,验证会传播到反应式表达式和观察者。用反应性语言(参见本文来说,它们分别是电抗导体电抗端点。这意味着他们可以采取反应性依赖。电抗导体也可用于创建电抗依赖性。input无功源。反应式源可用于创建反应式依赖,但严格来说不能采用反应式依赖(技术上renderUI实际上是output$uiOutCars不具有反应式依赖input$selectCar

话虽如此,这是另一种解决方法。它创建一个伪输入,它是一个反应式表达式(即,将传播验证消息)。

library(shiny)
library(data.table)

cars <- data.table(mtcars, keep.rownames = T )
setnames(cars, "rn", "name")

ui <- fluidPage(
  selectInput("cyl", "Cyl", c(4, 12)),
  uiOutput("uiOutCars"),
  h4("Filtered Table"),
  tableOutput("filteredTable")
)

server <- function(input, output, session) {

  availableCars <- reactive({
    choices <- cars[cyl == input$cyl, name]
    validate(need(try(length(choices) > 0),
                  "No cars with this cyl!"))
    choices

  })


  output$uiOutCars <- renderUI({
    selectInput(inputId = "selectCar", 
                label = "Car", 
                choices = availableCars(),
                selected = "Merc 230")
  })

  pseudoSelectCar <- reactive(
    {

      availableCars()
      # include other dependencies here
      input$selectCar

    })

  output$filteredTable <- renderTable({
    req(pseudoSelectCar()) # prevent warning on initialization
    cars[name == pseudoSelectCar()]
  })


}
Run Code Online (Sandbox Code Playgroud)

这个想法是,当重新评估伪输入的表达式时,如果任何依赖项验证失败,它们也会短路“输入”评估。否则,伪输入就等于输入值。

缺点是您必须input$selectCar在 的定义中显式列出所有依赖项pseudoSelectCar。好处是您只需在一个地方执行此操作,并且可以pseudoSelectCar在代码中本来要使用的其他任何地方使用input$selectCar