I have a html <input>
element that I want to accept only numbers and to be recognised on mobile devices as a number field. I also want invalid characters to be swallowed, just like for standard type=number
swallowing disallowed characters.
I've tried the obvious type=number
but it has a number of shortcomings. Specifically it allows 'e', '+' and '-' (at least in chrome), but these were easy to fix with some JS. The real problem is with the '.' character, I want to be able to enter floating point numbers e.g. '0.10', '5.5054', but don't want to be able to enter invalid strings like '0.10.1' for instance. I tried to resolve this by allowing only 1 '.' at a time but this failed as the input.value
gets massaged by the browser e.g. '5.' becomes '5', '5..' becomes null (!) and it seems impossible to get the raw string value typed in the input. The above means checking for existing '.'s and taking action appears to be a dead end...
Core questions:
- Is there a way I missing to inspect and conform the input?
- 'Is there a way of marking an input as a number without the logistical baggage of
type=number
?
Note:
* I realise that you can paste whatever you want in, I consider that behaviour pathological and shouldn't be covered by input prevention.
Update
To clarify, I have already tried keypress
, keydown
etc events and they aren't adequate as I want to see how many '.'s exist in the input currently to choose whether or not to allow another. At this point the input.value
has been massaged by the browser to remove '.'s. I want to conditionally allow characters based on the current number of '.'s that have been entered.
Example
HTML (angular style binding for brevity)
<input type="number" (keydown)="keyDown()">
JS
function keyDown($event: KeyboardEvent) {
const inputField = // obtain reference to input element
const value = inputField.value;
if ( value.indexOf('.') !== -1 && $event.key === '.') { // disallow another . if one is present
// ! input field prunes . so this check isn't sufficient
$event.preventDefault();
return;
}
// This is the crux of the problem e.g.
// type 5. into input field, value === 5
// type 5.. into the input field, value === null
// Since the . char is removed by the input element there's no way to know how many are present!
console.log(value);
}
Summary
- Is there a way to signal that an
<input>
is of type number without using thetype=number
attribute setting.- i.e. mobile devices recognise and display number pad etc
- For an
<input>
that hastype=number
is there a way to swallow all key input that doesn't result in a valid number- Before the character is added to the input by the browser, no janky deletion on
keyup
- Before the character is added to the input by the browser, no janky deletion on