Search code examples
rshinyuser-inputnumeric

Series of need(validate) in Shiny: Printing only the first case of failure


I am trying to create a Shiny app that has a user-specified input for p-value (should be a probability between 0 and 1). Before, I have had the user specify p-value using the sliderInput() function.

However, I find that the resolution is limited with sliderInput(). It is difficult for me to allow a user to define values like 0.001 versus 0.0000000001 and still use larger values like 0.4. As a result, I am not trying to allow users to input their p-value in a much more flexible manner using the Shiny textInput(). Then, they can easily type in values like 0.0000000001 or 1e-20 or 0.2 without frustratingly trying to move the slider perfectly only to find that such resolutions do not exist.

I think I have a working MWE. I am using the validate(need) format to guide users should they input something nonsensical. It may just be a finer detail, but currently, if a user types in a value of something like "hello", they get all three validate(need) messages from the application:

'P-value must be a decimal between 0 and 1.'
'P-value must be less than or equal to 1.'
'P-value must be greater than or equal to 0.'

My question is: Is it possible to tweak this code so that only the first validate(need) that fails gets printed? If there are other foreseeable problems related to using textInput() instead of sliderInput() despite working with numbers, feel free to share too. Thank you for your advice!

My MWE:

if (interactive()) {
    options(device.ask.default = FALSE)

    ui <- fluidPage(
        textInput("PValue", "P-value:", value = "0.05"),
        plotOutput('plot')
    )

    server <- function(input, output) {
        output$plot <- renderPlot({
            cat(str(input$PValue))

            validate(
                need(!is.na(as.numeric(input$PValue)), 'P-value must be a decimal between 0 and 1.'),
                need(as.numeric(input$PValue) <= 1, 'P-value must be less than or equal to 1.'),
                need(as.numeric(input$PValue) >= 0, 'P-value must be greater than or equal to 0.')
            )

            plot(input$PValue)
        })
        p
    }
    shinyApp(ui, server)
}

Solution

  • You could separate the three conditions:

    validate(need(is.numeric(input$PValue), 'P-value must be a decimal between 0 and 1.'))
    validate(need(as.numeric(input$PValue) <= 1, 'P-value must be less than or equal to 1.')),
    validate(need(as.numeric(input$PValue) >= 0, 'P-value must be greater than or equal to 0.'))
    

    shiny then checks the individual conditions one after the other and displays only an error message.