Handling both clicks and keypresses in React number input not working - javascript

I have part of some React code below, where I have a number input, I'd like to prevent people being able to click below 0, which I've done with the min attribute. However I've seen that it's possible to still manually key in negative numbers. After some googling I've seen that people can handle this with a keyPress check and looking at the character codes but for some reason I can't quite get this to work.
Are both handlers clashing with each other? My goal is to allow click increments to work for positive numbers and prevent negative and decimal numbers being allowed in the input.
It's a controlled input, where value is coming from state.
const handleChange = (e) => {
console.log(e.target.value);
setCount(e.target.value);
};
const handleKeyPress = (e) => {
console.log(e.target.value);
console.log(e.charCode);
if (e.charCode >= 48 && e.charCode <= 57) {
setCount(e.target.value);
}
};
return (
<section>
<h3>Input test</h3>
<form onSubmit={handleSubmit}>
<label htmlFor="amount">paragraphs:</label>
<input
type="number"
name="amount"
id="amount"
min="0"
value={count}
onKeyPress={handleKeyPress}
onChange={handleChange}
/>

You can format your value to absolute integer in your handleChange function and it would remove the zero and decimal separator on re-render:
const handleChange = (e) => {
setCount(Math.abs(parseInt(e.target.value)));
};
Or if you absolutely want to prevent "0" and "." characters to be entered, you can use preventDefault in your handleKeyPress function:
const handleKeyPress = (e) => {
if (e.charCode === 45 || e.charCode === 46) {
return e.preventDefault()
}
};

In this case you would like to use onKeyPress as a validator only. If validation fails, you can call e.preventDefault(). This way it will prevent to trigger onChange:
const handleKeyPress = (e) => {
if (e.charCode >= 48 && e.charCode <= 57) return
e.preventDefault()
};

Related

key charCode for virtual keyboard

I have the below code to allow the user input only numbers, this works in browser. But when I access on mobile I think I am not able to get the right key code. So what are the keycodes for the same. Isn't same as the web.
// block e char, dot, hiphen and spacebar
if (event.key === 'e' || [46, 45, 32].includes(event.charCode)) {
event.preventDefault();
}else{
// allow to input logic
}
What are the charCode for dot, hyphen and space which will work for both web and mobile keypad ?
Your code is using event.charCode, which does not exist.
event.which.charCode does. Also you do not tell us what event.
There are keypress, keydown, keyup, input and some do not set some of the expected event values
Tested on Android and iOS using browserstack
Only one that seems to work in React on Android
export default function App() {
const handleInput = (event) => {
// eslint-disable-next-line
event.target.value = event.target.value.replace(/[e\.\- ]/g, "");
console.log(event.target.value);
};
return (
<div className="App">
<input type="number" onInput={handleInput} />
</div>
);
}
Older answers
Keydown and the code names which is recommended
document.getElementById("positiveIntOnly").addEventListener("keydown",function(e) {
// block e char, dot, hyphen and spacebar
if (["KeyE", "Period", "Minus", "Space"].includes(e.code)) {
event.preventDefault();
console.log(e.code);
}
});
<input type="number" id="positiveIntOnly" />
Or as mentioned by TJ, e.key:
document.getElementById("positiveIntOnly").addEventListener("keydown",function(e) {
// block e char, dot, hyphen and spacebar
if ("e.- ".includes(e.key)) {
event.preventDefault();
console.log(e.key);
}
});
<input type="number" id="positiveIntOnly" />
Set a min and max and use a regexp to handle paste
<input type="number" id="positiveIntOnly" min="0" max="999" step="1"
oninput="this.value = this.value.replace(/[e\.\- ]/g,'')" />
You can just you the key property:
["e" ,"E", "-", ".", " "].includes(e.key)
You're not supposed to use the charCode property as it is deprecated.

How can I prevent other characters from being inputted on an input except numbers using Javascript

I am using Vue.JS (Bootstrap-Vue) to build a form, my input has the following code:
<b-form-input
v-mask="'####'"
number
type="number"
no-wheel
pattern="[0-9]"
step="1"
:class="{ 'hasError': $v.form.dobYear.$error }"
v-model.number="$v.form.dobYear.$model"
class="form-input"
name="year"
id="year"
maxlength="4"
min="1900"
max="2020"
#keydown="filterKey"
></b-form-input>
When a user presses down I want to prevent more than 4 characters to be entered, this works, but when testing, I can see period and dashes and other similar characters can also be added into the input and ignores the maximum of 4 characters. How can I update the following code to ensure nothing but numbers can be added to my input on mobile. I'm trying to detect if any of those unwanted keys are pressed then prevent the default action. (I've tested on Android Chrome)
filterKey(e) {
const value = e.target.value;
const key = e.key;
console.log(value, this.amount);
if (String(value).length === 4) {
//check if a number is pressed after 4 have been entered
if (!isNaN(Number(key))) {
e.preventDefault();
return;
} else if (key == 190 || key == 189 || key == 107 || key == 69) {
e.preventDefault();
return;
}
}
}
The following snippet will not allow anything to be entered into the input element if the length of the input's value is already 4, or if a non-numeric character is typed (but will allow 'Backspace' and 'Delete' keys):
EDIT : Implemented Hiws' suggestion to let the user type in numbers even if the length is 4, if some text is selected in the input element
function filterKey(e) {
let previousValue = e.target.value;
let key = e.keyCode || e.charCode;
if (key != 8 && key != 46) { // Ignore backspace and delete
if (
// preventDefault if length of input is 4 and no text is selected in the input
( String(e.target.value).length >= 4 && e.target.selectionStart === e.target.selectionEnd ) ||
// preventDefault if entered a space or non-number
!e.key.trim() || isNaN(e.key)
) {
// Prevent input if input length crosses 4,
// or if input is not a number
e.preventDefault();
// Include below line only if you have no other event listeners on the element, or its parents
e.stopImmediatePropagation();
return;
}
}
}
You block keys other than numbers only if number value already equals to 4. Try changing your blocking logic to:
if (String(value).length > 4 || !isNaN(Number(key)) || unwanted keyCodes) {
e.preventDefault();
return;
You can use a regex to test against the value of the input field and avoid messing with keyCodes.
if ( !/^[0-9]{0,4}$/.test(String(value)) ) {
e.preventDefault();
return;
}

Real time input text filtration which allows only numbers

Hello I'm trying to make real time input type="text" filter which allows only numbers and dot, using javascript.
I wrote
Javascript:
<script>
function thirdTaskFunction(evnt) {
evnt = evnt || window.event;
var charCode = evnt.which ? evnt.which : evnt.keyCode;
return /\d/.test(String.fromCharCode(charCode));
}
function thirdTaskFunction(evt) {
var charCode = (evt.which) ? evt.which : evt.keyCode;
if(charCode > 31 && (charCode < 48 || charCode > 57)) {
return false;
}
return true;
}
function thirdTaskFunction() {
var thirdInput = document.getElementById("thirdTaskInputText");
thirdInput = thirdInput.onchange = thirdTaskFuncion;
var valid = /^\-?\d+\.\d*$|^\-?[\d]*$/;
var number = /\-\d+\.\d*|\-[\d]*|[\d]+\.[\d]*|[\d]+/;
if(!valid.test(this.value)) {
var compare = this.value.match(number);
this.value = compare ? compare[0] : '';
}
}
</script>
HTML:
<div id="thirdTaskDIV">
<input id="thirdTaskInputText" type="text" placeholder="Type a number" autofocus onkeypressed="return thirdTaskFunction(event);">
</div>
I was trying many ways, every thirdTaskFunction() method wasn't work, I was tested solution on w3schools so maybe this is reason? But I think that I dont remember about something that make it works. And I know is very similar to "HTML text input allow only numeric input" but it didnt works.. So I hope somebody show me whats pappyn here.
One way to allow only numbers in an input field is using a keypress event listener. So you'll want to select the input field and give it an event listener, like this:
const inputField = document.querySelector("/*input field id here*/");
inputField.addEventListener("keypress", function(e){
if(e.keyCode > 48 && e.keyCode < 57){
e.preventDefault();
}
}
This function checks if the key that's pressed matches a number key, and if it doesn't, prevents the default action which in this case is printing the character to the input field.
If you have any questions, I'll do my best to answer them!
P.S. The keyCode numbers used are estimates based on memory, to get the key codes simply do a quick search on google for "ASCII key codes".
The event code (NOT keyCode since the keyCode property is deprecated) for the dot is Period and the event code for the numbers 0 to 9 comes in the form Digit0, Digit1 and so on.
Just use the keydown event listener to retrieve the event code and then use the includes() method to check if the current key has a code that includes "Digit" or "Period" and restrict input of that character if it doesn't include either of those two by using preventDefault() like this:
const input = document.getElementById('thirdTaskInputText');
function checkKey(e) {
if(e.code.includes("Digit") || e.code.includes("Period")) {
console.log("valid input");
} else {
e.preventDefault();
console.log("not a number!");
}
}
input.addEventListener('keydown', checkKey)
<input id="thirdTaskInputText" type="text" placeholder="Type a number">
Without the console logs, you can further simplify the above code to a single if statement using the bang operator ! like this:
const input = document.getElementById('thirdTaskInputText');
function checkKey(e) {
if(!(e.code.includes("Digit") || e.code.includes("Period"))) e.preventDefault();
}
input.addEventListener('keydown', checkKey)
<input id="thirdTaskInputText" type="text" placeholder="Type a number">

How can I prevent numeric inputs using VueJS

I need to create a validation that prevent the user from inputting numeric inputs on a textbox. I found some solution using a native javascript but it is not working on my side.
On my text box I have this trigger
v-on:keyup="preventNumericInput($event)">
And on my Vue I created a function on my class
preventNumericInput($event) {
console.log($event.keyCode); //will display the keyCode value
console.log($event.key); //will show the key value
var keyCode = ($event.keyCode ? $event.keyCode : $event.which);
if (keyCode > 47 && keyCode < 58) {
$event.preventDefault();
}
}
Can you help me with this?
As mentioned in my comment, keyup will be firing too late to prevent the value being entered into the input field. For example, think about holding a key down to enter the same value repeatedly; there is no key up.
Instead, usekeydown or keypress
<input #keypress="preventNumericInput">
Demo ~ http://jsfiddle.net/wadt08jm/1/
Input must be type number, otherwise isNaN won't work
<input type="number" :value="price" step="0.1" min="0" #input="onInput($event)" >
into input replace ',' by '.'
test if not number
if not number replace observable price by element.value
data () {
return { price: 0 }
},
methods: {
onInput (e: Event) {
const element = e.target as HTMLInputElement
const value = parseFloat(element.value === '' ? '0' : element.value.replace(',', '.'))
if (isNaN(value)) {
element.value = this.price.toString()
} else {
this.price = value
}
}
}

Restrict characters in input field

Is there a way to block users from writing specific characters in input fields? I tried the code below, but when a user enters disallowed characters, they appear for a brief period before disappearing. I want the input to remain unchanged when invalid characters are written.
I want to use onchange because other restriction methods do not seem to work on mobile devices. The problem I want to solve is that characters appear briefly before being removed.
function checkInput(ob) {
const invalidChars = /[^0-9]/gi;
if(invalidChars.test(ob.value)) {
ob.value = ob.value.replace(invalidChars, "");
}
};
<input class="input" maxlength="1" onChange="checkInput(this)" onKeyup="checkInput(this)" type="text" autocomplete="off" />
you can use try this,
$('.input').keyup(function () {
if (!this.value.match(/[0-9]/)) {
this.value = this.value.replace(/[^0-9]/g, '');
}
});
SEE THIS FIDDLE DEMO
Updated :
You can try this Code,
$(document).ready(function() {
$(".input").keydown(function (e) {
// Allow: backspace, delete, tab, escape and enter
if ($.inArray(e.keyCode, [46, 8, 9, 27, 13, 110]) !== -1 ||
// Allow: Ctrl+A
(e.keyCode == 65 && e.ctrlKey === true) ||
// Allow: home, end, left, right
(e.keyCode >= 35 && e.keyCode <= 39)) {
// let it happen, don't do anything
return;
}
// Ensure that it is a number and stop the keypress
if ((e.shiftKey || (e.keyCode < 48 || e.keyCode > 57)) && (e.keyCode < 96 || e.keyCode > 105)) {
e.preventDefault();
}
});
});
SOURCE
SEE UPDATED FIDDLE DEMO
UPDATED FOR ANDROID:
<EditText
android:id="#+id/editText1"
android:inputType="number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="#+id/textView1"
android:layout_marginTop="58dp"
android:layout_toRightOf="#+id/textView1"
android:maxLength="1" >
</EditText>
I think it may help you... using android:inputType="number" you can do that.
A combination of keypress and paste events does a trick:
var text = document.getElementById('text');
text.onkeypress = text.onpaste = checkInput;
function checkInput(e) {
var e = e || event;
var char = e.type == 'keypress'
? String.fromCharCode(e.keyCode || e.which)
: (e.clipboardData || window.clipboardData).getData('Text');
if (/[^\d]/gi.test(char)) {
return false;
}
}
<input class="input" maxlength="10" id="text" type="text" autocomplete="off" />
This code prevents from typing or pasting anything but a number. Also no blinking and invalid characters don't show up.
Works in IE7+.
Demo: http://jsfiddle.net/VgtTc/3/
All answers given so far suffer from at least one of the following accessibility issues:
They validate key codes, which does not work with non-QWERTY keyboard layouts.
They do not cover all input methods; especially drag&drop is often forgotten.
They alter the value, which resets the position of the caret.
They use the pattern attribute, but this does not provide feedback until the form is submitted.
Wouldn't it be a much better idea to actually validate the input before it's inserted?
The beforeinput event fires before the input's value is changed. The event has a data property which describes the content that the user wants to add to the input field. In the event handler, you simply check the data attribute, and stop the event chain if it contains disallowed characters.
We end up with the following very simple, very short code.
const input = document.getElementById("input");
const regex = new RegExp("^[0-9]*$");
input.addEventListener("beforeinput", (event) => {
if (event.data != null && !regex.test(event.data))
event.preventDefault();
});
<label for="input">Enter some digits:</label>
<input id="input" />
Some closing notes:
Accessibility: Provide a clear explanation of what input format is expected from the user. For example, you can use the title attribute of the input to show a tooltip explaining the expected format.
Security: This is client-side validation, and does not guarantee that the pattern is enforced when the form is sent to a server. For that, you'll need server-side validation.
Here's a little hack you could try: DEMO
What it does is that it colors every input text white and then changes it back to black if it suits your requirements. If you could live with the bit of lag that occurs when you enter a valid character.
function checkInput(ob) {
var invalidChars = /[^0-9]/gi
if (invalidChars.test(ob.value)) {
ob.value = ob.value.replace(invalidChars, "");
}
else {
document.getElementById('yourinput').style.color = '#000';
}
};
function hideInput(ob) {
document.getElementById('yourinput').style.color = '#FFF';
};
html
<input id="yourinput" class="input" maxlength="1" onKeydown="hideInput(this)" onKeyup="checkInput(this)" type="text" autocomplete="off" />
css
input {color:#FFF;}
check this code,
$('.input').keypress(function(e) {
var a = [];
var k = e.which;
for (i = 48; i < 58; i++)
a.push(i);
if (!(a.indexOf(k)>=0))
e.preventDefault();
});
​
<input id="testInput"></input>
<script>
testInput.onchange = testInput.oninput = restrict;
function restrict() {
testInput.value = testInput.value.replace(/[^a-z]/g, "");
}
</script>
I came up with something slightly different. oninput instead of onkeyup/onkeydown, and onchange instead of onpaste.
I restrict invalid characters on both keypress and paste events like:
<input type="text" onkeydown="validateKey(event)" onpaste="validatePaste(this, event)">
And define functions to handle these events inside tab or a separate javascript file:
<script>
function validateKey(e) {
switch(e.keyCode) {
case 8,9,13,37,39:
break;
default:
var regex = /[a-z .'-]/gi;
var key = e.key;
if(!regex.test(key)) {
e.preventDefault();
return false;
}
break;
}
}
function validatePaste(el, e) {
var regex = /^[a-z .'-]+$/gi;
var key = e.clipboardData.getData('text')
if (!regex.test(key)) {
e.preventDefault();
return false;
}
}
</script>

Categories