The simplest way will be to convert the string to a number and then check if it's valid. As the value of inputs is always a string even if you use type="number", though it is good to use it if you just want numbers as the input.
You can use isNaN(+value). Here + will convert a string to a number.
<input
type="text"
onChange={(e) => {
const value = e.target.value;
console.log(!isNaN(+value)); // true if its a number, false if not
}}
/>
Some test cases:
console.log(!isNaN(+"54"));
console.log(!isNaN(+"23xede"));
console.log(!isNaN(+"test"));
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Answer from Manas Khandelwal on Stack OverflowNote: As mentioned this is a simple way, there can be workarounds to bypass this, for a robust solution you can have a look here: Check whether variable is number or string in JavaScript
The simplest way will be to convert the string to a number and then check if it's valid. As the value of inputs is always a string even if you use type="number", though it is good to use it if you just want numbers as the input.
You can use isNaN(+value). Here + will convert a string to a number.
<input
type="text"
onChange={(e) => {
const value = e.target.value;
console.log(!isNaN(+value)); // true if its a number, false if not
}}
/>
Some test cases:
console.log(!isNaN(+"54"));
console.log(!isNaN(+"23xede"));
console.log(!isNaN(+"test"));
Run code snippetEdit code snippet Hide Results Copy to answer Expand
Note: As mentioned this is a simple way, there can be workarounds to bypass this, for a robust solution you can have a look here: Check whether variable is number or string in JavaScript
You can cast to number and then check if it's Nan
isNaN(parseInt('0')) // false
isNaN(parseInt('f')) // true
As noted in the comments parseInt() will return a number for a string with a number in it. Using Number on the other hand will return Nan
isNaN(Number('55')) // false
isNaN(Number('55bob')) // true
React Input validation if empty or number
reactjs - How do I validate a number input within a React component - Stack Overflow
Only numbers. Input number in React - javascript
How to only accept numbers in a input[type=text]
If you want to keep your error messages separate I would recommend to reorganize your state.
So scalable solution (you may add more controls by just adding them to state) may look like:
class NumberControlsWithErrorMessage extends React.Component {
constructor(props) {
super(props);
this.state = {
inputs: [
{ name: 'price', value: 0, error: ''},
{ name: 'downP', value: 0, error: '' },
{ name: 'term', value: 0, error: '' },
{ name: 'interest', value: 0, error: '' }
]
};
}
handleInputChange = (idx, event) => {
const target = event.target;
const name = target.name;
let error = '';
if (isNaN(target.value)) {
error = `${name} field can only be number`
}
if (!target.value) {
error = `${name} field cannot be empty`
}
this.state.inputs[idx] = {
...this.state.inputs[idx],
value: target.value,
error
}
this.setState({
inputs: [...this.state.inputs]
});
}
render() {
return (
<form>
{this.state.inputs.map((input, idx) => (
<div>
<label htmlFor="">{input.name}</label>
<input type="text" value={input.value} onChange={(e) => this.handleInputChange(idx, e)}/>
{input.error && <span>{input.error}</span> }
</div>
))}
</form>
);
}
}
Working example
Also if you are building a complex form, you may want to try some React solution for forms, where all the mechanism for listening to events, state updates, validatoin are already handled for you. Like reactive-mobx-form
A straightforward way of handling multiple objects needing validation is to store an errors object in your state that has a property for each input field. Then you conditionally render the error underneath each input field depending on whether or not it has an error. Here is a very basic example:
class Calculator extends React.Component {
constructor(props) {
super(props);
this.state = {
price: 0, downP: 0, term: 0, interest: 0,
errors: { price: '', downP: '', term: '', interest: '' }
};
}
handleValidation = () => {
const { price, downP, loan, interest } = this.state;
let errors = { price: '', downP: '', term: '', interest: '' };
if (!price) {
errors.price = 'Price is required';
} else if (isNaN(price)) {
errors.price = 'Price must be a number';
}
if (!downP) {
errors.downP = 'Down Payment is required';
}
// Rest of validation conditions go here...
this.setState({ errors });
}
render() {
const { errors } = this.state;
return (
<form>
<input name="price" value={this.state.price} onChange={this.handleChange} />
{errors.price != '' && <span style={{color: "red"}}>{this.state.errors.price}</span>}
<input name="downP" value={this.state.downP} onChange={this.handleChange} />
{errors.downP != '' && <span style={{color: "red"}}>{this.state.errors.downP}</span>}
{/** Rest of components go here */}
</form>
);
}
}
You can choose whether or not to run validation once the form submits or on every keypress and that will affect how when those messages appear and disappear, but this should give you an idea on how you would manage error messages specific to each input field.
Simply way in React
<input
onKeyPress={(event) => {
if (!/[0-9]/.test(event.key)) {
event.preventDefault();
}
}}
/>
I tried to mimic your code and noticed that there's an issue on React with <input type='number' />. For workaround, check this example and try it yourself: https://codepen.io/zvona/pen/WjpKJX?editors=0010
You need to define it as normal input (type='text') with pattern for numbers only:
<input type="text" pattern="[0-9]*"
onInput={this.handleChange.bind(this)} value={this.state.financialGoal} />
And then to compare the validity of input:
const financialGoal = (evt.target.validity.valid) ?
evt.target.value : this.state.financialGoal;
The biggest caveat on this approach is when it comes to mobile --> where keyboard isn't in numeric but in normal alphabetic format.
Hey guys, I am using react hook form and zod to manage forms. I want to know how to only accept numbers in a input[type=text]. Please Help
You can still use the min and max attributes for the input, but have some custom logic for checking that the input value doesn't go outside of that interval.
Example
class App extends React.Component {
state = { value: 0 };
handleChange = event => {
let { value, min, max } = event.target;
value = Math.max(Number(min), Math.min(Number(max), Number(value)));
this.setState({ value });
};
render() {
return (
<input
value={this.state.value}
onChange={this.handleChange}
type="number"
min="1"
max="250"
/>
);
}
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"></div>
Run code snippetEdit code snippet Hide Results Copy to answer Expand
This is because the onChange function expects it to be numeric. When you are entering backspace that field becomes blank which is not a valid number and it's trying to call onChange with blank value that is why you are not able to edit it
Simply way in React
<input
onKeyPress={(event) => {
if (!/[0-9]/.test(event.key)) {
event.preventDefault();
}
}}
/>
I tried to mimic your code and noticed that there's an issue on React with <input type='number' />. For workaround, check this example and try it yourself: https://codepen.io/zvona/pen/WjpKJX?editors=0010
You need to define it as normal input (type='text') with pattern for numbers only:
<input type="text" pattern="[0-9]*"
onInput={this.handleChange.bind(this)} value={this.state.financialGoal} />
And then to compare the validity of input:
const financialGoal = (evt.target.validity.valid) ?
evt.target.value : this.state.financialGoal;
The biggest caveat on this approach is when it comes to mobile --> where keyboard isn't in numeric but in normal alphabetic format.
The UI Kit we use in our company has some input component that allows to enter any symbol. But I need to make it a numeric field. So I need to ignore any non-digit symbols that a user tries to enter in this field. For that on every key down I check the key with isFinite() and if it's not then I just prevent the default behavior.
But sometimes a user needs to use combinations like ctrl+A or some other ones. So my solution is not good because I also need to check for all possible shortcuts.
Also worth to mention that the input is controlled by React Form Hook and not useState
You can use regex.
!firstName.match(/\d/)
\d checks for the numbers
function validateName(name) {
var isValidName = true;
if(/[!@#$%^&*(),.?":{}|<>]/g.test(name) || !/^[A-Z]/.test(name) || /\d+/g.test(name)) {
isValidName = false;
}
return isValidName;
}
validateName("David")