Why does shiny display validation message twice?

shiny
#1

How can we ensure the user sees the validation error message only once? because Within the server function, there is if block, depending on the data read, different validation needs to be done and displayed to the user Therefore, refusing to use req() instead

Even in Shiny validation page, they had displayed error message twice:
https://shiny.rstudio.com/articles/validation.html

Also, if I were using different language, the below link might have helped.

Even though **Stackoverflow had similar question here but referring different issue **

It meant something different.

I am referring to "Please select a data set" message displaying twice

library(shiny)

ui <- fluidPage(
    
    titlePanel("Validation App"),
    
    sidebarLayout(
        sidebarPanel(
            selectInput("data", label = "Data set",
                        choices = c("", "mtcars", "faithful", "iris"))
        ),
        
        # Show a plot of the generated distribution
        mainPanel(
            tableOutput("table"),
            plotOutput("plot")
        )
    )
)
server <- function(input, output) {
    
    data <- reactive({
        validate(
            need(input$data != "", "Please select a data set")
        )
        get(input$data, 'package:datasets')
    })
    
    output$plot <- renderPlot({
        hist(data()[, 1], col = 'forestgreen', border = 'white')
    })
    
    output$table <- renderTable({
        head(data())
    })
    
}
shinyApp(ui,server)

If there is an error, ideally only 1 time, user should be notified if not it might be annoying.

0 Likes

#2

First let's figure out why the message is being displayed twice. Shiny is behaving as expected as both output$plot and output$table are using data(), so both outputs should display a validation message.
Changing the app to see that this is true...

library(shiny)

ui <- fluidPage(
    
    titlePanel("Validation App"),
    
    sidebarLayout(
        sidebarPanel(
            selectInput("data", label = "Data set",
                        choices = c("", "mtcars", "faithful", "iris"))
        ),
        
        # Show a plot of the generated distribution
        mainPanel(
            "Table: ", tableOutput("table"),
            "Plot: ", plotOutput("plot")
        )
    )
)
server <- function(input, output) {
    
    data <- reactive({
        validate(
            need(input$data != "", "Please select a data set")
        )
        get(input$data, 'package:datasets')
    })
    
    output$plot <- renderPlot({
        hist(data()[, 1], col = 'forestgreen', border = 'white')
    })
    
    output$table <- renderTable({
        head(data())
    })
    
}
shinyApp(ui,server)


To make sure the same message does not happen twice, validations should occur at the render* level, not an internal reactive. The example below will validate for the plot, but will only require for the table. The data value is set to FALSE for invalid state.

Example:

server <- function(input, output) {
    
    data <- reactive({
      if (nchar(input$data) == 0) return(FALSE)
      get(input$data, 'package:datasets')
    })
    
    output$plot <- renderPlot({
      validate(
        need(data(), "Please select a data set")
      )
      hist(data()[, 1], col = 'forestgreen', border = 'white')
    })
    
    output$table <- renderTable({
      req(data())
      head(data())
    })
    
}
shinyApp(ui,server)

1 Like

#3

Thanks barret for solution...I accepted your answer.
In my actual script, within server function, file read (input from the user) is checked for the file format (if/else condition).
For each if/else condition, there is unique validation.

But in render* the output of the data() is rendered whatever the output from data(). Since we can't be sure which kind of format the user might be uploading, couldn't write if block in reactive data and validate in render*

0 Likes