ben*_*dae 6 validation r shiny
我试图validate在R Shiny中使用,以防止在不应该显示输出时显示它们。当reactive在input内部创建验证时使用验证,uiOutput并且验证引发错误时,该错误不会传递给依赖项reactive或output。
阅读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!为:
我的期望是,filteredTable也input$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)
为了完整起见,根据我对其他答案的评论,严格来说,您不能将验证消息传播到输入(输入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