3

I have a bug when I set the value from the state and change the value in a input.

when you write in the input and you try to correct the text the cursor move to the end.

This is my element

<div className="campo">
  <p>Nombre</p>
  <div className="campo-input">
    <input
     type="text"
     name="name"
     value={this.state.name}
     onChange={this.handleInputChangeUpperCase}
     />
  </div>
</div>

This is my function

handleInputChangeUpperCase = (e) => {
    let { name, value } = e.target;
    this.setState({ [name]: value.toUpperCase() });
  };

Working Snippet:

class App extends React.Component {
  state = {
    name: "Ronaldo",
  };
  
  // This is the function
  handleInputChangeUpperCase = (e) => {
    let { name, value } = e.target;
    this.setState({
      [name]: value.toUpperCase(),
    });
  };
  render() {
  
  // This is the Element
    return (
      <div className="campo">
        <p> Nombre </p>
        <div className="campo-input">
          <input
            type="text"
            name="name"
            value={this.state.name}
            onChange={this.handleInputChangeUpperCase}
          />
          {this.state.name}
        </div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Dhaval Jardosh
  • 7,151
  • 5
  • 27
  • 69
Edsen
  • 77
  • 3
  • 7

4 Answers4

2

To control where the cursor is in an input field, use selectionStart, which indicates where your selected text begins. As long as you don't set selectionEnd, you'll just move the cursor to the desired position.

For instance, let's move to the position "1", just after the first character. For input "123", that should be "1|23"...

document.getElementById('text-area').selectionStart = 1;
document.getElementById('text-area').focus()
  <input id="text-area" type="text" value="123"/>

For your situation, if you want the cursor to move to the start of the string, set .selectionStart = 0. If you want it to go back to where it was originally, save the value with var tempstart = ...selectionStart, and then restore it after you do the data change, .selectionStart = tempstart.

Source: Developer.Mozilla.org: HTMLInputElement.setSelectionRange()

HoldOffHunger
  • 18,769
  • 10
  • 104
  • 133
2

Based on the original answer: https://stackoverflow.com/a/49648061/7427111

class App extends React.Component {
  state = {
    name: "Ronaldo",
  };
  
  handleInputChangeUpperCase = (e) => {
  
    // Here is the addition
    const pointer = e.target.selectionStart;
    const element = e.target;
    window.requestAnimationFrame(() => {
      element.selectionStart = pointer;
      element.selectionEnd = pointer;
    });

    let { name, value } = e.target;
    this.setState({
      [name]: value.toUpperCase(),
    });
  };
  render() {
    return (
      <div className="campo">
        <p> Nombre </p>
        <div className="campo-input">
          <input
            type="text"
            name="name"
            value={this.state.name}
            onChange={this.handleInputChangeUpperCase}
          />
          {this.state.name}
        </div>
      </div>
    );
  }
}

ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>
Dhaval Jardosh
  • 7,151
  • 5
  • 27
  • 69
1

If you need just toUpperCase as formatting then you can use css instead. It seems the simplest solution is described here https://stackoverflow.com/a/3724990/12868043

Artem
  • 129
  • 4
0

That behaviour seems to be happening with .toUpperCase();

handleInputChangeUpperCase = e => {    
    this.setState({ [e.target.name]: e.target.value });
};

If you don't require the text to be upper case immediately on input, I would apply the method outside of the setState

rantao
  • 1,621
  • 4
  • 14
  • 34