2

I have a component of basic editable list items that operates as such:

enter image description here

My problem is that the cursor does not move into the input box onChange, making a hassle for the user to always click twice. I tried https://coderwall.com/p/0iz_zq/how-to-put-focus-at-the-end-of-an-input-with-react-js but it did not work. Component looks like:

import React from 'react';

import MyComponent from '../utils/MyComponent';


export default class BasicList extends MyComponent {

    constructor(props) {
        let custom_methods = ['renderItemOrEditField', 'toggleEditing', 'moveCaretAtEnd'];
        super(props, custom_methods);
        this.state = {editing: null};
    }

    moveCaretAtEnd(e) {
        var temp_value = e.target.value
        e.target.value = ''
        e.target.value = temp_value
    }

    renderItemOrEditField(item) {
        console.log(item);
        if (this.state.editing === item.id) {
            return (
                <input
                  onKeyDown={ this.handleEditField }
                  type="text"
                  className="form-control"
                  ref={ `${item.type}_name_${ item.id }` }
                  name="title"
                  autofocus
                  onFocus={this.moveCaretAtEnd}
                  defaultValue={ item.name }
                />
            );
        } else {
            return (
                <li
                  onClick={this.toggleEditing.bind(null, item.id)}
                  key={item.id}
                  className="list-group-item">
                    {item.name}
                </li>
            );
        }
    }

    toggleEditing(item_id) {
        this.setState({editing: item_id});
    }


    render() {
        let li_elements = null;
        let items = this.props.items;

        if (items.length > 0) {
          li_elements = items.map((item) => {
              return (
                  this.renderItemOrEditField(item)
                //   {/* }<li key={item.id}>
                //       {item.name} -
                //       <button onClick={() => {this.props.deleteCallback(this.props.item_type, item.id, item.name)} }>
                //         Delete
                //       </button>
                //   </li> */}

              );
          });
        }

        return (
          <div>
            <h4>{this.props.title}:</h4>
                <ul className="list-group">
                    {li_elements}
                </ul>
          </div>
        );
    }
}

The items I'm working with now only have a name and ID (type denotes a 'role' or 'task')

How can I make the cursor start at the end of the input box text on change?

2
  • SO to be sure I understand--when you click on the li it changes to an input, and you would like the cursor at the end of the text in that input once it has changed to an input from an li... is that it? Commented Jun 5, 2017 at 19:17
  • yes that's exactly it. right now the input box opens up with no cursor in it Commented Jun 5, 2017 at 19:23

2 Answers 2

1

Autofocus triggers when a component is mounted. Not sure that's happening by your conditional render. You could moving your conditional logic to a separate container and that should trigger a mount each time it's shown.

Sign up to request clarification or add additional context in comments.

Comments

1

I ended up setting focus as in the callback that causes the input box to show:

toggleEditing(item_id) {
        // this syntax runs the function after this.setState is finished
        this.setState({editing: item_id}, function() {
            this.textInput.focus();
        });
    }

Then the original solution given worked:

   // https://coderwall.com/p/0iz_zq/how-to-put-focus-at-the-end-of-an-input-with-react-js
    moveCaretAtEnd(e) {
        var temp_value = e.target.value
        e.target.value = ''
        e.target.value = temp_value
    }

and

 <input
      onKeyDown={ this.handleEditField }
      type="text"
      className="form-control"
      ref={(input) => { this.textInput = input; }}
      name="title"
      autofocus
      onFocus={this.moveCaretAtEnd}
      defaultValue={ item.name }
      onChange={(event) => this.editItem(event)}
      style={ {maxWidth: 500} }
    />

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.