Restrict input type in shiny field
Asked Answered
M

4

9

As it is, numericInput accepts both string and numeric inputs. If a string is entered it is converted to NA (try with the code below). Is there a way of not allowing the user to type a string in a numeric field in shiny?

ui <- fluidPage(
  numericInput("num", label = "text not allowed", value = 1),
  verbatimTextOutput("value")
)

server <- function(input, output) {
  output$value <- renderPrint({ input$num })      
}

shinyApp(ui = ui, server = server)

So far, I have added a text output next to the numeric input that warns the user that only numbers are accepted if she enters a string in a numericInput field. This solution is far from ideal for me.

I want it to be impossible for the user to enter a character value in a numeric field.

Mcbrayer answered 7/7, 2016 at 13:13 Comment(0)
R
14

You can add validate to your expression, so only number inputs will be allowed. I'm using windows 7 64-bit with Google Chrome (IE will work too)

Note: Shiny version 0.13.2, doesn't work on Firefox.

library(shiny)
ui <- fluidPage(
  numericInput("num", label = "text not allowed", value = 1),
  verbatimTextOutput("value")
)
server <- function(input, output) {

  numbers <- reactive({
    validate(
      need(is.numeric(input$num), "Please input a number")
    )
  })
  output$value <- renderPrint({ numbers() })      
}
shinyApp(ui = ui, server = server)
Ratafia answered 7/7, 2016 at 13:22 Comment(8)
thanks for the reply, but I am looking for a way of not allowing string input in a numeric field. Something like a numeric_only=T argument in numericInput. I want it to be impossible for the user to enter a character value in a numeric field.Mcbrayer
As you can see, there is no way of entering the character into that field. I dont see what you are getting atRatafia
What version of shiny are you using, Im on 0.13.2? Please updateRatafia
well, you can enter a character, only it will tell you it's the wrong thing to do. I would ideally like to user to be unable to even type the "d" in this example: imgur.com/GwHCPeHMcbrayer
just updated to 0.13.2 but I can still enter "d" and get an error as in the picture I sent..Mcbrayer
Something is up on your side then, make sure to restart your machine. As I physically cannot enter a string into that box. By the way, so as others, as the answer gets voted upRatafia
Yes, it works on Chrome. It is weird that it doesn't work in RStudios Viewer or Window. FTR, could you also add to your answer which os you use? I am in Windows 8.1Mcbrayer
Why does this work on Chrome but not within RStudio viewer?Zandrazandt
H
2

IMO the simplest way to accomplish that, it's adding the observer to your input, and when forbidden sign is detected (what probably requires your own function detecting forbidden signs), just delete it form input using updateInput feature.

Update:

observe({

if(is.null(input$myTextInput)) {
  vec <- NULL
  return()
} else vec <- input$myTextInput

  vec <- removeForbiddenSignsFunction(vec)

  updateTextInput(session, "myTextInput", value = vec)
})

Example of removing forbidden signs function (this one removes signs forbidden in Windows file names):

  removeForbiddenSignsFunction <- function(vec) {
  forbidden <- c("|", "?", "*")
  notAllowed <- c(">", "<", ":","/"," ")


  for(i in 1:length(forbidden)) {
    if(grepl(paste0("\\",forbidden[i]),vec)) {
      vec <- sub(paste0("\\",forbidden[i]),"",vec)
    }
  }

  for(i in 1:length(notAllowed)) {
    if(grepl(notAllowed[i],vec)) {
      vec <- sub(notAllowed[i],"",vec)
    }
  }

  if(grepl("\\\\",vec)) vec <- sub("\\\\","",vec)
  if(grepl("\"",vec)) vec <- sub("\"","",vec)

  return(vec)
}

It is splitted for forbidden and notAllowed due to regex special signs (not allowed in regular expressions and windows file names).

Havens answered 17/8, 2016 at 14:17 Comment(3)
Include an example usage?Hypervitaminosis
that is a good solution, although technically it doesn't disable string input.Mcbrayer
Sure, iyop45. I added some update for previous post, as you can see.Jackleg
H
2

My solution was to use an observe() to monitor the input and replace it if it didn't meet the required parameters using updateNumericInput().

observe({
  if (!is.numeric(input$num)) {
    updateNumericInput(session, "num", 0)
  }
})
Hazelwood answered 27/11, 2018 at 4:48 Comment(1)
Welcome to SO @dtownley! This works too, but it doesn't, strictly speaking, restrict the input type.Mcbrayer
S
2

Here is a solution using HTML rather than Shiny. The solution is to add a pattern attribute to the HTML input tag. It will not remove the undesired characters, but the field will turn, say, pink to let the user know that an invalid character has been typed.

1-- Let the background becomes pink when invalid is raised. For that, we need to add a style in the CSS. In Shiny, this is achieved by adding in the ui a style tag in the head tag that will be attached to input[type='text']:invalid with

tags$head(
    tags$style(HTML("input[type='text']:invalid {background-color: pink;}"))
)

2-- create the ui with the above as well as a text input field, e.g.:

ui <- fluidPage(
    tags$head(
        tags$style(HTML("input[type='text']:invalid {background-color: pink;}"))
      ),
  textInput("mySolution", label = "Only letters are valid here", value = ""),
)

3-- modify this ui to add a pattern to the input tag:

ui <- searchreplaceit(ui, "input", list(id="mySolution"), 
        "input", list(pattern="[A-Za-z]*"), replace=FALSE)

This is it! the server function does not need anything, as validation is all performed whithin the page. Launch the page with

server <- function(input, output, session) { }
shinyApp(ui = ui, server = server)

The function to add attributes to a tag is given here

searchreplaceit <- function(branch, whattag, whatattribs, totag, toattribs, replace=TRUE) {
    if ("name" %in% names(branch)) {
        if ((branch$name == whattag)&&(identical( branch$attribs[names(whatattribs)], whatattribs))) {
            branch$name    <- totag
            branch$attribs <- if (replace) {toattribs} else { modifyList(branch$attribs, toattribs)}
        }
    }
    if ("shiny.tag" %in% class(branch)) {
        if (length(branch$children)>0) for (i in 1: length(branch$children)) {
            if (!(is.null(branch$children[[i]]))) {
                branch$children[[i]] = searchreplaceit(branch$children[[i]], whattag, whatattribs, totag, toattribs, replace)
        } }
    } else if ("list" %in% class(branch)) {
        if (length(branch)>0) for (i in 1:length(branch) ) {
            if (!(is.null(branch[[i]]))) {
                branch[[i]] <- searchreplaceit(branch[[i]], whattag, whatattribs, totag, toattribs, replace)
        } }
    } 
    return(branch)
}

A related version was given in Edit a shiny.tag element

When you do not type a letter:

result with improper input

Spruill answered 11/6, 2021 at 10:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.