How to get the raw value an <input type="number"> field?

59,214

Solution 1

According to the WHATWG, you shouldn't be able to get the value unless it's valid numeric input. The input number field's sanitization algorithm says the browser is supposed to set the value to an empty string if the input isn't a valid floating point number.

The value sanitization algorithm is as follows: If the value of the element is not a valid floating-point number, then set it to the empty string instead.

By specifying the type (<input type="number">) you're asking the browser to do some work for you. If, on the other hand, you'd like to be able to capture the non-numeric input and do something with it, you'd have to rely on the old tried and true text input field and parse the content yourself.

The W3 also has the same specs and adds:

User agents must not allow the user to set the value to a non-empty string that is not a valid floating-point number.

Solution 2

It doesn't answer the question, but the useful workaround is to check

edQuantity.validity.valid

The ValidityState of an object gives clues about what the user entered. Consider a type="number" input with a min and max set

<input type="number" min="1" max="10">

We always want to use .validity.valid.

Other properties only give bonus information:

┌──────────────┬────────┬────────╥───────────┬─────────────────┬────────────────┐
│ User's Input │ .value │ .valid ║ .badInput │ .rangeUnderflow │ .rangeOverflow │
├──────────────┼────────┼────────╫───────────┼─────────────────┼────────────────┤
│ ""           │ ""     │ true   ║ false     │ false           │ false          │ valid because field not marked required
│ "1"          │ "1"    │ true   ║ false     │ false           │ false          │ 
│ "10"         │ "10"   │ true   ║ false     │ false           │ false          │
│ "0"          │ "0"    │ false  ║ false     │ true            │ false          │ invalid because below min
│ "11"         │ "11"   │ false  ║ false     │ false           │ true           │ invalid because above max
│ "q"          │ ""     │ false  ║ true      │ false           │ false          │ invalid because not number
│ "³"          │ ""     │ false  ║ true      │ false           │ false          │ superscript digit 3
│ "٣"          │ ""     │ false  ║ true      │ false           │ false          │ arabic digit 3
│ "₃"          │ ""     │ false  ║ true      │ false           │ false          │ subscript digit 3
└──────────────┴────────┴────────╨───────────┴─────────────────┴────────────────┘

You'll have to ensure that the the browser supports HTML5 validation before using it:

function ValidateElementAsNumber(element)
{
   //Public Domain: no attribution required.
   if ((element.validity) && (!element.validity.valid))
   {
      //if html5 validation says it's bad: it's bad
      return false;
   }
   
   //Fallback to browsers that don't yet support html5 input validation
   //Or we maybe want to perform additional validations
   var value = StrToInt(element.value);
   if (value != null)
      return true;
   else
      return false;
}

Bonus

Spudly has a useful answer that he deleted:

Just use the CSS :invalid selector for this.

input[type=number]:invalid {
    background-color: #FFCCCC;
}

This will trigger your element to turn red whenever a non-numeric valid is entered.

Browser support for <input type='number'> is about the same as :invalid, so no problem there.

Read more about :invalid here.

Solution 3

input.focus();
document.execCommand("SelectAll");
var displayValue = window.getSelection().toString();

Solution 4

Track all pressed keys based on their key codes

I suppose one could listen to the keyup events and keep an array of all characters entered, based on their keycodes. But it's a pretty tedious task and probably prone to bugs.

http://unixpapa.com/js/key.html

Select the input and get the selection as a string

document.querySelector('input').addEventListener('input', onInput);

function onInput(){
  this.select(); 
  console.log( window.getSelection().toString() )
}
<input type='number'>

All credit to: int32_t

Share:
59,214
mistertodd
Author by

mistertodd

Any code is public domain. No attribution required. జ్ఞా &lt;sup&gt;🕗&lt;/sup&gt;🕗 Yes, i do write i with a lowercase i. The Meta Stackexchange answer that I am most proud of

Updated on January 22, 2021

Comments

  • mistertodd
    mistertodd over 3 years

    How can i get the "real" value of an <input type="number"> field?


    I have an input box, and i'm using newer HTML5 input type number:

    <input id="edQuantity" type="number">
    

    This is mostly supported in Chrome 29:

    enter image description here

    What i now need is the ability to read the "raw" value the user has entered in the input box. If the user has entered a number:

    enter image description here

    then edQuantity.value = 4, and all is well.

    But if the user enters invalid text, i want to color the input-box red:

    enter image description here

    Unfortunately, for a type="number" input box, if the value in the text-box is not a number then value returns an empty string:

    edQuantity.value = "" (String);
    

    (in Chrome 29 at least)

    How can i get the "raw" value of an <input type="number"> control?

    i tried looking through Chrome's list of other properties of the input box:

    enter image description here

    i didn't see anything that resembles the actual input.

    Nor could i find a way to tell if the box "is empty", or not. Maybe i could have inferred:

    value          isEmpty        Conclusion
    =============  =============  ================
    "4"            false          valid number
    ""             true           empty box; not a problem
    ""             false          invalid text; color it red
    

    Note: You can ignore everything after the horizontal rule; it's just filler to justify the question. Also: don't confuse the example with the question. People might want the answer to this question for reasons other than coloring the box red (One example: converting the text "four" into the latin "4" symbol during the onBlur event)

    How can i get the "raw" value of an <input type="number"> control?

    Bonus Reading

  • Bergi
    Bergi over 10 years
    Doesn't work in Opera. It says valid even if you input a string.
  • mistertodd
    mistertodd over 10 years
    Opera supports the .validity property, but doesn't correctly handle .valid?!
  • Bergi
    Bergi over 10 years
    It does, but when is a number input invalid? It just acts as if the input was empty. A typeMismatch might make sense, but that is only for email or url types…
  • mistertodd
    mistertodd over 10 years
    It would be useful if user agents did not allow the user to set the value to a non-empty string that is not a valid floating-point number. But if whatwg says it cannot be done; then that's the answer. Workaround for my current need added below.
  • mistertodd
    mistertodd over 10 years
    @Bergi The table above gives examples where number inputs can be invalid: "q", "11" (then the max is 10), "0" (when the min is 1), "" (then the element is required)
  • Bergi
    Bergi over 10 years
    Opera does not have that badInput property on Validity objects, which seems to be the reason for the different behavior. Is that property standardized anywhere?
  • mistertodd
    mistertodd over 10 years
    @Bergi .badInput was added 11/20/2012. But nobody should be looking at badInput to see if input is valid; they should be looking at .valid. It is possible (and correct) for .badInput to be false, and still have invalid input. .valid is defined as the absence of any validation errors (E.g. mismatches, overflows, underflows), of which .badInput is only one kind of error. Note the chart above where .badInput is false, but the input is still invalid.
  • mistertodd
    mistertodd over 10 years
    That solution was tried elsewhere, and doesn't work. Especially when the users presses Delete, Backspace, Ctrl+X, Ctrl+V, Right-click-cut, Right-click-paste.
  • sandstrom
    sandstrom over 10 years
    I agree with you, basically what the OP asked isn't possible. However, both hacks I mentioned (and they are hacks, I don't deny that) do work to some extent. Perhaps they can be useful to someone, in some case?
  • Mark Amery
    Mark Amery about 10 years
    Rather than using a fictitious StrToInt method that is left for the reader to implement, wouldn't doing return !isNan(element.value) be adequate?
  • mistertodd
    mistertodd about 10 years
    @MarkAmery I'm not sure. Would !isNan("two") recognize a "good" value?
  • Mark Amery
    Mark Amery about 10 years
    By specifying the type (<input type="number">) you're asking the browser to do some work for you. Personally, I was just asking mobile browsers to show a numeric keypad, and got the validation as an unpleasant extra. Most of these problems stem from the fact that the type attribute determines both validation rules and rules about what input mechanism to display, but it's quite possible to want to show a numeric keyboard to mobile users without also wanting number validation applied to desktop users. HTML 5.1 will at least solve this problem eventually with the inputmode attribute.
  • njzk2
    njzk2 almost 10 years
    but when the browser does not do enough, I would like to be able to complete it. such as removing spaces in the input, inferring the decimal point...
  • njzk2
    njzk2 almost 10 years
    also, in various languages, such as french, there are 2 words for number. one for numbers as identifiers, such as credit card numbers, and one for counting numbers, such as floating point numbers.
  • njzk2
    njzk2 almost 10 years
    amazingly, the selection thing seems to work. What are the limitation of that method?
  • httpete
    httpete about 9 years
    The trickiest thing about getting into html5 validation is that the validity object is the source of truth - if you do <input type="number"> and type "foo" in the field, and then do input.value, there IS NO VALUE as you would expect. It only has a value, when input.validity.valid = true.
  • Moti Korets
    Moti Korets about 9 years
    You can use type="tel" to achieve numeric pad in mobile.
  • fregante
    fregante over 8 years
  • fregante
    fregante over 8 years
    Limitations: the text is visually selected. If the user types something the content will be gone
  • Andy
    Andy over 8 years
    @MotiKorets doesn't work for entering floating point numbers as iPhones don't put a decimal point on the keyboard. Unfortunately devs are pretty screwed at the moment as far as providing a nice floating point entry UX...
  • Brad Kent
    Brad Kent about 8 years
    Doesn't work in firefox : bugzilla.mozilla.org/show_bug.cgi?id=85686 (note that this bug was filed in 2001 !!)
  • Goblinlord
    Goblinlord over 7 years
    Asking the browser to do work for you is great... but then how the @#*&^$#@$ do I get it to display a certain input method in mobile and NOT do the work for me (instead of breaking)?
  • vsync
    vsync almost 6 years
    Firefox, as always, is correct. This should not work and is a bug
  • vsync
    vsync almost 6 years
    Edited with a live demo which shows how bad this method is