I have a number input field that sets the new value through the state when the user is typing. This works fine. If I however add decimals to it (toFixed), the cursor will jump to the end of the input after typing only one digit. This happens when I, for example, delete what is there and type something else. If I instead add a digit between the first one and the decimal point, the cursor does not jump. Has anyone experienced this before, and what was the solution?
Fiddle to show the problem: https://jsfiddle.net/Inverness/k04yvq1u/
constructor() {
super()
this.state = {
number: 1
}
this.handleInputChange = this.handleInputChange.bind(this)
}
handleInputChange(event) {
console.log(event.target.value)
this.setState({
number: event.target.value
})
}
render() {
return (
<div>
<input
type="number"
value={ parseFloat(this.state.number).toFixed(2) }
onChange={ this.handleInputChange }
/>
</div>
)
}
I've had success using the onBlur
event handler to simply format the input field to the way you need it after the user has finished typing.
Adding a bit of info in the form field label that the input will be limited to 2 decimal spaces should help alleviate any UX issues with changing a value that the user has provided.
constructor() {
super()
this.state = {
number: 1
}
this.handleInputChange = this.handleInputChange.bind(this)
this.formatInput = this.formatInput.bind(this)
}
handleInputChange(event) {
console.log(event.target.value)
this.setState({
number: event.target.value
})
}
formatInput() {
const num = this.state.number
this.setState({
number: parseFloat(num).toFixed(2)
})
}
render() {
return (
<div>
<input
type="number"
value={ this.state.number }
onChange={ this.handleInputChange }
onBlur={ this.formatInput }
/>
</div>
)
}
JSFiddle
I had something similar to this happen. The main issue here is that you are re-formatting what they type in as they type. Since react is using javascript to change the value, the browser can't guess where the cursor is supposed to go, so it just jumps to the end. The way I solved this was by only updating when the user enters something that matches the toFixed format. Something roughly equivalent that should work is setting value={this.state.number}
on your input. Then the on change should look something like this:
handleInputChange = e => {
let val = e.target.value
if (/^[\d]*\.?[\d]{0,2}$/.test(val)) {
this.setState({number: val})
}
}
That way the input value still is constrained to be a two-decimal floating point format, but the user has more freedom to type it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With