Shiny: numericInput() does not respect min and max values

Created on 12 Aug 2015  路  14Comments  路  Source: rstudio/shiny

You can make the value of a numericInput() exceed the maximum and minum allowed values by typing in the value manually. This was reported by astudent taking the tutorial.

For example, the code below limits the numeric input to values from 1 to 100. However, the input accepts values that exceed the range, so long as you type them in manually.

library(shiny)

ui <- fluidPage(
 numericInput("num", "", min = 1, max = 100, value = 25),
 textOutput("text")
)

server <- function(input, output) {
 output$text <- renderText(input$num)
}

shinyApp(ui, server)
Advanced High Low Type

Most helpful comment

Any news on this 2018 bug ? This really affects users of the final application.... and probably break the code behind.... (following issue)

All 14 comments

I think the behavior of number inputs is browser-dependent. I think we would have to add some Javascript to limit the range. Some info about that here: http://www.htmlgoodies.com/html5/tutorials/whats-new-in-html5-forms-handling-numeric-inputs-using-the-number-and-range-input-types.html

Hm, there's also a report that numericInputs used to be red when invalid values were used, but that it doesn't do this anymore.

https://groups.google.com/d/msg/shiny-discuss/Ny25P88nObU/88i-X7ItAAAJ

It looks like the red outline was removed in Bootstrap 3, which we used starting in Shiny 0.11. See https://github.com/twbs/bootstrap/issues/8093 for a discussion of why.

Still, it might make sense for Shiny to validate number inputs and indicate when they're invalid.

I'm relatively new to shiny and I don't know if the problem introduces here was solved, but I can still write value bigger than the max in some cases. The following code shows a situation where it is allowed:

    shinyUI(pageWithSidebar(
        headerPanel('Download Example'),
        sidebarPanel(
           sliderInput("sampSize", "Sample Size",min = 2, max = 20,  step = 2,  value = 10),
           numericInput("n", "N:", min = 0, max = 100, value = 50)
        ),
        mainPanel()
    ))

However if I remove the sliderInput and only leave the numericInput, I will not be able to input a value greater than the max, instead I will see a pop-up box that tells me I can't.

Both behaviour scenarios are on the same browser "Chrome"

@wch I tried to explain and recap the issues about numericInput here: https://github.com/rstudio/shiny/issues/1022#issuecomment-282305308

I highlight the following points related to the numericInput issues:

  • if the input is not inside a form (like the example in this issue), submit and validation machinery (native or custom) is not triggered
  • if the form doesn't contain an input or button of type submit, submit and validation process, as explained in the above issue reference, is not triggered
  • I found only a bug: even if there is a submit button, the native validation popups are not triggered due to a preventDefault call in the click handler (as explained in the above issue reference)

How to create always a form to contain the input(s), if the reactive process needs to be off when the input is invalid is beyond these issues.

I would close #927 (this issue), #1022 (the issue I proposed to call preventDefault only if the form is valid), and #1593 (because it is almost an enhancement or a duplicate), after adding that change suggested in #1022.

@wch any thought?

@albertosantini, Can this issue be temporarily resolved by having the inputs for the min/max be reactive to a reactive values list?

@jerburt well, in my notes I am talking about validation machinery (see the reference issue above) on front end side; you can always validate the inputs on server side.

Indeed. I personally always check the validity:

isValid_num <- reactive({
  !is.null(input$num) && input$num>0 && input$num<100
})

And I test the validity for the outputs:

output$text <- renderText({
  if(isValid_num()){
   .....
  }else{ # optional
    # throw an alert with shinyBS
  }
})

Any progress on this topic?

I agree. Here is my demo. I didn't find any valid way to control the keyboard free numeric input. So I use reactive() to check the validity and force to use the max if keyboard input is greater than max. Then I put a red note to let users aware of input value if it is greater than max.

 library(shiny)

 shinyApp(
 ui = fluidPage(

 numericInput("nn", "Enter a number (Max is 10):",
             value=5, min=1, max=10, step=1),
 htmlOutput("note")
 ),
 server = function(input, output) {

input_received<-reactive({
 if(input$nn> 10){
   max
 }else{
   input$nn
 }
})
 textnote<-reactive({
 if(input$nn<= 10){
   paste("Your input is: ",input$nn)
 }else{
   paste0("<font color=\"#e05959\"><b>", "Note: your input beyond Max, 10 will be used as input. ", "</b></font>")
  }
  })
   output$note<-renderText({
   HTML(textnote() )
  })   
 })

Your solution is nice, but if somebody still uses the wrong input it will not help.

I did a workaround with Javascript to control this and it works fine: I control the value with javascript with the following code:

setInterval(function(){
  if($("#step4").find(".col-sm-2").eq(5).find(".shiny-bound-input").val() > 1 | $("#step4").find(".col-sm-2").eq(5).find(".shiny-bound-input").val() < 0) {
    controlvalue = 1
  } else {
    controlvalue = 2
  }
  controlvalue
  Shiny.onInputChange("inputcontrol", controlvalue)
}, 50)

the variable "inputcontrol" is passed back to R and controlled by an observer:

    controlvalue <- reactive({
        req(input$bruttonettofaktor)
        input$inputcontrol
    })

    observe({
        req(input$bruttonettofaktor)
        req(controlvalue())

        if(controlvalue() == 1) {

            shinyalert("Achtung!", paste0("Payfaktor muss zwischen 0 und 1 liegen! Wert wird auf 0,4 zur眉ckgesetzt"), type = "error")
            updateNumericInput(session, "bruttonettofaktor", min = 0.01, max = 1, value = 0.4, step = 0.01)
        }
    })

If you have any questions regarding this code, do not hesitate to contact me :-)

Any news on this 2018 bug ? This really affects users of the final application.... and probably break the code behind.... (following issue)

The only news is that it's still as broken as it was in 2018, as far as I see.

Hello,

If you want, you can use the number input provided by my package shinyChakraSlider. It's impossible to enter a value outside the min-max range with this number input.

You can also combine it with a slider:

chakra

library(shiny)
library(shinyChakraSlider)

ui <- fluidPage(
  br(),
  chakraNumberInput("number",
                    label = tags$span(
                      style = "font-size: 20px; font-style: italic;",
                      "Chakra Number Input"
                    ),
                    value = 5, min = 0, max = 10, step = 0.5,
                    size = "lg",
                    numberInputOptions = numberInputOptions(
                      width = "200px",
                      fontSize = "15px",
                      fontColor = "navyblue",
                      borderColor = "gold",
                      borderWidth = "medium",
                      focusBorderColor = "navyblue",
                      stepperColor = c("palegreen", "palevioletred")
                    )
  ),
  br(),
  verbatimTextOutput("numbervalue"),
  br(),
  actionButton("numberupdate", "Update value"),

  br(), br(),
  tags$hr(style = "border-color: lime; border-top-width: 10px;"),
  br(),

  chakraSliderInput("slider",
                    label = tags$span(
                      style = "font-size: 20px; font-style: italic;",
                      "Chakra Slider"
                    ),
                    value = 5, min = 0, max = 10, step = 0.5,
                    width = "50%", size = "lg",
                    numberInputOptions = numberInputOptions(
                      width = "25%",
                      fontSize = "15px",
                      fontColor = "navyblue",
                      borderColor = "gold",
                      borderWidth = "medium",
                      focusBorderColor = "navyblue",
                      stepperColor = c("palegreen", "palevioletred")
                    ),
                    trackColor = c("orangered", "darkolivegreen"),
                    thumbOptions = thumbOptions(
                      width = "30px",
                      height = "30px",
                      color = "seashell",
                      borderColor = "darkmagenta",
                      borderWidth = "6px"
                    )
  ),
  br(),
  verbatimTextOutput("slidervalue"),
  br(),
  actionButton("sliderupdate", "Update value")
)

server <- function(input, output, session){

  output[["numbervalue"]] <- renderPrint({
    input[["number"]]
  })

  observeEvent(input[["numberupdate"]], {
    updateChakraSliderInput(session, "number", value = 8)
  })

  output[["slidervalue"]] <- renderPrint({
    input[["slider"]]
  })

  observeEvent(input[["sliderupdate"]], {
    updateChakraSliderInput(session, "slider", value = 8)
  })

}

shinyApp(ui, server)
Was this page helpful?
0 / 5 - 0 ratings