Only numbers. Input number in React
I'm trying to exclude minus and plus from input, but it's going wrong:
handleChange(event) {
const value = event.target.value.replace(/\+|-/ig, '');
this.setState({financialGoal: value});
}
Render input code:
<input style={{width: '150px'}} type="number" value={this.state.financialGoal} onChange={this.handleChange}/>
Solution 1:
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.
Solution 2:
Simply way in React
<input
onKeyPress={(event) => {
if (!/[0-9]/.test(event.key)) {
event.preventDefault();
}
}}
/>
Solution 3:
one line of code
<input value={this.state.financialGoal} onChange={event => this.setState({financialGoal: event.target.value.replace(/\D/,'')})}/>
Solution 4:
If you want to maintain input type='number'
(probably for mobile devices to trigger the numeric keyboard) you should use onInput
instead of onChange
to capture your event changes.
Using onInput
fixed a bug where typing text into a number input would bypass the validation I had assigned to it in onChange
. Once I fixed this function to be called in onInput
it triggered in all instances.
Here's an example of what I'm doing:
<input
type='number'
id={`player${index}Score`}
className='form-control'
pattern='[0-9]{0,5}'
onInput={(event) => this.enterScore(event, index)}
value={this.props.scoreLabel(this.state.scores[index])}
/>
I hope this helps!
EDIT - 08-03-2018:
I came up with a better solution. Use type='tel' along with a pattern regex within the input component itself.
The nuts and bolts of how I wired this up is here:
class Input extends React.Component {
state = {message: '3'};
updateNumber = (e) => {
const val = e.target.value;
// If the current value passes the validity test then apply that to state
if (e.target.validity.valid) this.setState({message: e.target.value});
// If the current val is just the negation sign, or it's been provided an empty string,
// then apply that value to state - we still have to validate this input before processing
// it to some other component or data structure, but it frees up our input the way a user
// would expect to interact with this component
else if (val === '' || val === '-') this.setState({message: val});
}
render() {
return (
<input
type='tel'
value={this.state.message}
onChange={this.updateNumber}
pattern="^-?[0-9]\d*\.?\d*$"
/>
);
}
}
ReactDOM.render(<Input />, document.getElementById('main'));
I have an example of this working on Codepen here
Solution 5:
To stop typing, use
onKeyPress
notonChange
.Using
event.preventDefault()
insideonKeyPress
means STOP the pressing event .-
Since
keyPress
handler is triggered beforeonChange
, you have to check the pressed key (event.keyCode
), NOT the current value of input (event.target.value
)onKeyPress(event) { const keyCode = event.keyCode || event.which; const keyValue = String.fromCharCode(keyCode); if (/\+|-/.test(keyValue)) event.preventDefault(); }
Demo below 👇🏻
const {Component} = React;
class Input extends Component {
onKeyPress(event) {
const keyCode = event.keyCode || event.which;
const keyValue = String.fromCharCode(keyCode);
if (/\+|-/.test(keyValue))
event.preventDefault();
}
render() {
return (
<input style={{width: '150px'}} type="number" onKeyPress={this.onKeyPress.bind(this)} />
)
}
}
ReactDOM.render(<Input /> , document.querySelector('#app'));
<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>
<section id="app"></section>