PythonQQ
PythonQQ

Reputation: 111

Add or focus to next input field when press keyboard ENTER button

I am studying React and Material-ui.

I want to make several input fields within a component, the number and value of these fields are received as props from a parent component. I added a function to move the focus when a user press the Enter button, or create new field if its the last field.

The current code has 15 refs (I know it's stupid, but I think It'll not be more than 15). The problem is that the focus does not move to a new field when it is created. Can you suggest a better way?

class ResponseInput extends Component {
    componentWillMount() {
        this.refs = [...Array(15)].map(r => React.createRef())
    }

    changeFocus = index => {
        if (index < this.props.inputs.length - 1) {
            this.refs[index + 1].current.focus();
        } else {
            this.props.addInput();
        }
    }

    render() {
        const { inputs, addInput, handleChangeInput } = this.props;

        return (
            <List>
                {inputs.map((item, index) => (
                    <ListItem key={index} >
                        <Input
                            value={item}
                            inputRef={this.refs[index]}
                            onChange={(event) => handleChangeInput (index, event)}
                            onKeyPress= {(event) => {
                                if (event.key === 'Enter') {
                                    this.changeFocus(index);
                                }
                            }}
                            // autoFocus
                        />
                    </ListItem>
                ))}
            </List>
        );
    }
}

Upvotes: 1

Views: 6234

Answers (2)

Alvin Theodora
Alvin Theodora

Reputation: 946

https://codesandbox.io/s/7wojmxv0oq

<Input autoFocus={index+1>originalInputsLength} .../>

Use autoFocus={index+1>originalInputsLength} checking which means if the input length exceeds original inputs length (user adding the list) then set autoFocus to that newly-created <Input/>.

originalInputsLength is initialized in App's constructor as state, then passed down as props to <ResponseInput inputs={inputs} addInput={this.addInput} originalInputsLength={originalInputsLength}/>

class App extends React.Component {
  constructor(props){
    super(props);
    const inputs = [1, 2, 3, 4, 5];
    this.state = {
      inputs: inputs,
      originalInputsLength: inputs.length,
    };
  }

Upvotes: 1

Gabriele Petrioli
Gabriele Petrioli

Reputation: 195992

Adding autoFocus={true} to the Input should fix it.

render() {
    const { inputs, addInput, handleChangeInput } = this.props;

    return (
        <List>
            {inputs.map((item, index) => (
                <ListItem key={index} >
                    <Input
                        autoFocus={true}
                        value={item}
                        inputRef={this.refs[index]}
                        onChange={(event) => handleChangeInput (index, event)}
                        onKeyPress= {(event) => {
                            if (event.key === 'Enter') {
                                this.changeFocus(index);
                            }
                        }}
                        // autoFocus
                    />
                </ListItem>
            ))}
        </List>
    );
}

Demo at https://codesandbox.io/s/10089vq54l

Upvotes: 1

Related Questions