How to set cursor position inside Textarea in ReactJs?

Refresh

December 2018

Views

379 time

1

Is there a way to programmatically set the cursor position inside a textarea?

My use-case is tagging users.

When a user enters @tar, I'm displaying suggestions, a user will click on one of them (for example @tarik) but the focus will be lost, which is expected. I need to return focus on specific position which I know how to calculate.

I'm using Textarea from react-textarea-autosize

I'm defining my ref in the constructor:

 this.textareaInput = React.createRef();

I'm assigning a component to ref:

 <Textarea
                ref={this.textareaInput}
                rows={1}
                value={comment}
                onChange={this.handleInputChanged}
                tabIndex={tabIndex || 0}
              />

And with this line, I should be able to manipulate with cursor position, but I'm not.

this.textareaInput.current._ref.focus();    
this.textareaInput.current._ref.selectionStart = 1;

or

 this.textareaInput.current._ref.focus(); 
 this.textareaInput.current._ref.selectionEnd = 3;

None of this examples works.

NOTE: Hardcoded values are used just to test the code.

I've tried to use setSelectionRange method too, no success.

3 answers

0

I found solution setting both selectionStart and selectionEnd on the same value.

0

Try this:

HTML:

<div id="container">
    <!-- This element's contents will be replaced with your component. -->
</div>

React-jsx:

 class TodoApp extends React.Component {

       constructor(props){
         super(props);
         this.state = {
            scriptString: ''
         };
       }
       handleKeyDown(event) {
          if (event.keyCode === 9) { // tab was pressed
              event.preventDefault();
              var val = this.state.scriptString,
                  start = event.target.selectionStart,
                  end = event.target.selectionEnd;

              this.setState({"scriptString": val.substring(0, start) + '\t' + val.substring(end)}, () => this.refs.input.selectionStart = this.refs.input.selectionEnd = start + 1);
          }
      }
      onScriptChange(event) {
         this.setState({scriptString: event.target.value});
      }
      render() {
          return (
              <textarea rows="30" cols="100" autofocus="true"
                        ref={this.textareaInput}
                        rows={1}
                        onFocus={ this.onFocus } 
                        onKeyDown={this.handleKeyDown.bind(this)}
                        onChange={this.onScriptChange.bind(this)} 
                        value={this.state.scriptString}/>



          );
      }
    }

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

I think the problem is that custom <Textarea> block doesn't have a .focus() method.

You can try this code:

import TextareaAutosize from 'react-textarea-autosize'

class MyComponent extends React.Component {
    componentDidMount() {
        this.inputRef.focus()
    }

    inputRef = ref => (this.inputRef = ref)

    render() {
        return <TextareaAutosize inputRef={this.inputRef} />
    }
}

Found on GitHub