I'm trying to use validate in R shiny to prevent outputs from showing when they shouldn't be. When a validated reactive is used in creating an input inside a uiOutput and the validation throws an error, this error does not get passed on to a depending reactive or output.
Reading https://shiny.rstudio.com/articles/validation.html and using reactlog has me thinking that the issue lies in the generated input not depending on the validated reactive.
The article states:
Shiny will: [...] pass a validation error to any reactive expression or observer object that depends on it
I'm unsure what an input inside a uiOutput really is, but I suspect it's neither a reactive expression nor an observer.
Consider the following example:
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)
Initial state:
When changing the cyl input from 4 to 12 (no cars with 12 cylinders exist in cars), the selectCar input is not shown. The validation message No cars with this cyl! is:
My expectation was that the filteredTable also stops showing, because input$selectCar should not have a proper value. However, it seems to retain its last value when availableCars() did not yet throw the error.
Is it possible to pass on the validation error "through" an input generated by a uiOutput?
EDIT
@TimTeaFan adds that neither does it work when using updateSelectInput (thanks for checking!):
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)