I just had the same problem and discovered an alternative solution using the validation API - works without black magic in all major browsers (Chrome, Firefox, Safari) except IE. This solution simply prevents users from entering invalid values.
I also included a fallback for IE, which is not nice but works at least.
Context: onInput function is called on input events, setInputValue is used to set the value of the input element, previousInputValue contains the last valid input value (updated in setInputValue calls).
function onInput (event) {
const inputValue = event.target.value;
// badInput supported on validation api (except IE)
// in IE it will be undefined, so we need strict value check
const badInput = event.target.validity.badInput;
// simply prevent modifying the value
if (badInput === true) {
// it's still possible to enter invalid values in an empty input, so we'll need this trick to prevent that
if (previousInputValue === '') {
setInputValue(' ');
setTimeout(() => {
setInputValue('');
}, 1);
}
return;
}
if (badInput === false) {
setInputValue(inputValue);
return;
}
// fallback case for IE and other abominations
// remove everything from the string expect numbers, point and comma
// replace comma with points (parseFloat works only with points)
let stringVal = String(inputValue)
.replace(/([^0-9.,])/g, '')
.replace(/,/g, '.');
// remove all but first point
const pointIndex = stringVal.indexOf('.');
if (pointIndex !== -1) {
const pointAndBefore = stringVal.substring(0, pointIndex + 1);
const afterPoint = stringVal.substring(pointIndex + 1);
// removing all points after the first
stringVal = `${pointAndBefore}${afterPoint.replace(/\./g, '')}`;
}
const float = parseFloat(stringVal);
if (isNaN(float)) {
// fallback to emptying the input if anything goes south
setInputValue('');
return;
}
setInputValue(stringVal);
}
inputmode
that could be set tonumeric
to show a numeric keyboard. Unfortunately no browser supports it yet, according to mozilla – Capsulatetype='number'
is set. – Parlourinputmode
attribute: it is still not supported in any browser by default (see caniuse.com/#search=inputmode), but can optionally be enabled in Firefox by setting thedom.forms.inputmode
flag. – Parlourtype=number
?? – Degradingpattern
is not an input-blocking behavior; apattern
only blocks in upon submit (in Chrome at least). And some input-blocking is browser-controlled; themin/max
andmin/max-length
fields do block input, a possible accessibility problem that is on the browser to fix. – Voodoo