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)