Lavanya Mohan
Lavanya Mohan

Reputation: 1516

React.js cursor focus issue on chrome

I have a simple react class which renders a controlled input box of type number.

var Form = React.createClass({
  getInitialState: function() {
    return { value: 12.12 };
  },

  handleChange: function(e) {
    this.setState({ value: e.target.value });
  },

  render: function() {
    return ( 
      <input
        onChange = {(e) => this.handleChange(e)}
        type = "number"
        value = {this.state.value}
      />
    );
  }
});

ReactDOM.render( <Form /> , document.getElementById('container'));

This code is present in this jsfiddle.

To change the value, when I delete the numbers one by one and delete the decimal point, the focus suddenly shifts to the start of the input box.

This happens on latest Chrome browser (54.0.2840.87) but not on Firefox.

If I use a defaultValue instead of value in state, on Chrome, even when I add a decimal value to the number, the focus shifts to the start. (The issue happens both on adding decimal value or on deleting the decimal part) Please refer to this jsfiddle.

I saw the answer to a similar question here. But the problem persists in Chrome when I try to delete numbers till decimal point.

Is there a way to get around this problem?

Thanks in advance for your help.

Upvotes: 1

Views: 858

Answers (2)

Lavanya Mohan
Lavanya Mohan

Reputation: 1516

I wanted to use an input box of type 'number' (for stepper, etc.), so did a work around by using refs. I took this idea of using refs from an answer to a similar question here.

I do not use defaultValue in the input tag but set the initial value in componentDidMount. And on change, I set value in a variable for future use.

var Form = React.createClass({
  componentDidMount() {
    this.input.value = "123.12";
  },

  handleChange: function(e) {
    this.value = e.target.value;
  },

  render: function() {
    return ( 
      <input
        onChange = {(e) => this.handleChange(e)}
        type = "number"
        ref={(elem) => this.input = elem}
      />
    );
  }
});

ReactDOM.render( <Form /> , document.getElementById('container'));

Please find jsfiddle code here.

Upvotes: 1

Niyoko
Niyoko

Reputation: 7672

It happens because your type="number". The e.target.value variable will have type of number too. Since there is no number that has value 12. (happens when you delete last decimal number after decimal point), then e.target.value will simply has value of 12, so the value jump from 12.1 to 12 (note that two characters deleted at the same time). It seems that Chrome doesn't like that change and behave strangely.

The solution for this problem is to simply change your input type to text, and validate your text box on submit.
Or simply strip invalid characters on text box change.

var Form = React.createClass({
  getInitialState: function() {
    return { value: 12.12 };
  },

  handleChange: function(e) {
    this.setState({ 
        value: e.target.value.replace(/([^0-9\.])/g, '')
    });
  },

  render: function() {
    return ( 
	    <input
  	    onChange = {(e) => this.handleChange(e)}
    	  type = "text"
      	value = {this.state.value}
      />
    );
  }
});

ReactDOM.render( <Form /> , document.getElementById('container'));
<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="container"></div>

Upvotes: 0

Related Questions