ReganPerkins
ReganPerkins

Reputation: 1665

React autoFocus sets cursor to beginning of input value

I have a controlled input that has a value initially showing. I have set that input to autoFocus but the cursor appears at the beginning of the input when I am wanting it to appear at the end. I understand this might be because the autoFocus is added before the value is but I'm not 100% sure.

What would be the best way to accomplish the cursor initializing at the end of the input field?

var Test = React.createClass({

    getInitialState: function() {
        return {
           teamId: 'fdsfds'
        };
    },

    render: function() {
        return (
                <input type="text" autoFocus value={this.state.teamId} onChange={this.setTeamId} />
        );
    },

    setTeamId: function(event) {
        this.setState({ teamId: id });
    },

});

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

https://jsfiddle.net/69z2wepo/34486/

Upvotes: 25

Views: 26660

Answers (7)

Colum Kelly
Colum Kelly

Reputation: 21

A TypeScript solution for functional components using a callback ref:

const inputRef = useCallback((node: HTMLInputElement | null) => {
    if (node) {
      const length = node.value.length
      node.setSelectionRange(length, length)
    }
  }, [])

return (
  <input ref={inputRef} type="text" autoFocus value={state}>
)

Upvotes: 0

Alejandro De Castro
Alejandro De Castro

Reputation: 2247

This way the text of the input will be selected, ready to edit

<input
  type="text"
  defaultValue="Untitled"
  autoFocus
  onFocus={e => e.currentTarget.select()}
/>

Upvotes: 1

user3792423
user3792423

Reputation: 1

In TypeScript:

private inputDOM: HTMLInputElement | null;

public componentDidMount() {
    if (this.inputDOM != null) {
        this.inputDOM.value = '';
        this.inputDOM.value = this.state.newRegionName;
    }
}

public render() {
    return <input ref={(ref: HTMLInputElement | null) => this.inputDOM = ref} type="text" autoFocus={true} value={this.state.inputValue} />;
}

Upvotes: 0

Ted A.
Ted A.

Reputation: 2302

One solution:

<input
  type="text"
  autoFocus
  value={this.state.teamId}
  onChange={this.setTeamId}
  onFocus={function(e) {
    var val = e.target.value;
    e.target.value = '';
    e.target.value = val;
  }}
/>

https://jsfiddle.net/o3s05zz4/1/

Adaptation of this answer: https://stackoverflow.com/a/2345915/1589521

Upvotes: 46

Spadar Shut
Spadar Shut

Reputation: 15797

This actually works:

componentDidMount() {
    const input = this.input;
    const length = input.value.length;
    input.focus();
    input.setSelectionRange(length, length);
}

render() {
   return (
       <input ref={ref => this.input = ref} ... >
   )
}

PS. If you need to support IE8 and below you'll need to use IE-specific checks.

Upvotes: 9

dannyjolie
dannyjolie

Reputation: 11339

Setting the input value inside componentDidMount seems to do the trick, but it feels like a hack:

componentDidMount: function(){
    this.inputElement.value = this.state.teamId;
},

render: function() {
    var that = this;
    return <input ref={function(ref){that.inputElement = ref;}} type="text" autoFocus value={this.state.teamId} onChange={this.setTeamId} />;
},

https://jsfiddle.net/yuk13tuu/

Upvotes: 0

thealexbaron
thealexbaron

Reputation: 1577

Looks like the html attribute autofocus doesn't take any parameters to specify where the cursor should start. See mdn documentation.

Sitepoint has a great tutorial explaining your options for setting cursor position from within an input box.

As for the reacty side of things, you'll simply put your jQuery (or other cursor related code) in the componentDidMount lifecycle method.

Upvotes: -1

Related Questions