para chamar o evento onChange depois de pressionar a tecla Enter

204

Eu sou novo no Bootstrap e preso com esse problema. Eu tenho um campo de entrada e, assim que digito apenas um dígito, a função de onChangeé chamada, mas quero que seja chamada quando pressionar 'Enter' quando o número inteiro tiver sido inserido. O mesmo problema para a função de validação - ela chama muito cedo.

var inputProcent = React.CreateElement(bootstrap.Input, {type: "text",
  //bsStyle: this.validationInputFactor(),
  placeholder: this.initialFactor,
  className: "input-block-level",
  onChange: this.handleInput,
  block: true,
  addonBefore: '%',
  ref:'input',
  hasFeedback: true
});
Bill Lumbert
fonte

Respostas:

404

De acordo com o React Doc , você pode ouvir eventos do teclado, gostando onKeyPressou onKeyUpnão onChange.

var Input = React.createClass({
  render: function () {
    return <input type="text" onKeyDown={this._handleKeyDown} />;
  },
  _handleKeyDown: function(e) {
    if (e.key === 'Enter') {
      console.log('do validate');
    }
  }
});

Atualização: Use React.Component

Aqui está o código usando React.Component que faz a mesma coisa

class Input extends React.Component {
  _handleKeyDown = (e) => {
    if (e.key === 'Enter') {
      console.log('do validate');
    }
  }

  render() {
    return <input type="text" onKeyDown={this._handleKeyDown} />
  }
}

Aqui está o jsfiddle .

Atualização 2: Use um componente funcional

const Input = () => {
  const handleKeyDown = (event) => {
    if (event.key === 'Enter') {
      console.log('do validate')
    }
  }

  return <input type="text" onKeyDown={handleKeyDown} />
}
canal
fonte
2
E você também gostaria de vincular o processo de validação ao onBlurevento.
wuct
5
Mesma solução de uma maneira mais compacta com referência ao texto de entrada:<input ref='reference' onKeyPress={(e) => {(e.key === 'Enter' ? doSomething(this.refs.reference.value) : null)}} />
musemind 30/07/16
5
@musemind Na verdade, você não precisa usar ref. <input onKeyPress={e => doSomething(e.target.value)}é suficiente.
wuct
4
@musemind O objetivo de usar um método de classe em vez de uma função embutida é evitar a criação de uma nova função sempre que onKeyPressacionada. É uma melhoria sutil de perf.
wuct
1
fiddle anexado não está mais funcionando, por favor verifique, de qualquer forma resposta agradável
Pardeep Jain
52

Você pode usar onKeyPress diretamente no campo de entrada. A função onChange altera o valor do estado em cada alteração do campo de entrada e, após pressionar Enter, chama uma pesquisa de função ().

<input
    type="text"
    placeholder="Search..."
    onChange={event => {this.setState({query: event.target.value})}}
    onKeyPress={event => {
                if (event.key === 'Enter') {
                  this.search()
                }
              }}
/>
Admir
fonte
esta resposta funciona para mim e não a resposta aceita acima.
Karthik shankar
Se você tiver uma forma pesada, eu recomendaria criar uma função fora do método de renderização e passá-la como referência, assim como onKeyPress={this.yourFunc}a função de seta gorda será recriada em cada renderização.
Viktor
isso está funcionando para o caso em que o evento onKeyPress também é gravado para entrada e caso pai. obrigado.
Naveen Kumar PG
OuonKeyPress={event => event.key === 'Enter' && this.search()}
camden_kid
24

pressionar Enter quando o foco em um controle de formulário (entrada) normalmente aciona um submitevento (onSubmit) no próprio formulário (não na entrada), para que você possa vinculá this.handleInput-lo ao formulário onSubmit.

Como alternativa, você pode vinculá-lo ao blurevento (onBlur) no inputqual acontece quando o foco é removido (por exemplo, tabulação para o próximo elemento que pode obter o foco)

Luca
fonte
3
Isso é muito mais limpo do que usar onKeyPress.
Blackus
1
Pensei que uma vez que o alvo é diferente, event.target.valuenão está disponível
Izkata
@ Izkata, o que você diz é absolutamente correto; minha resposta pode exigir uma maneira diferente de lidar com as coisas no handleInputmétodo do controlador . Fazer de acordo com a minha resposta cobriria você quando o usuário pressionar enter enquanto focado na entrada e ao ativar um submitbotão / entrada.
Luca
Na maioria das situações em aplicações web não existem formas, apenas entradas, pelo que esta resposta não é relevante para a maioria dos casos de uso, IMHO
vsync
@ vsync pode não ser relevante para a maioria, mas ainda é válido para uma parte - e definitivamente não está incorreto, acho que não vale a pena um voto negativo?
Luca
8

Você pode usar event.key

function Input({onKeyPress}) {
  return (
    <div>
      <h2>Input</h2>
      <input type="text" onKeyPress={onKeyPress}/>
    </div>
  )
}

class Form extends React.Component {
  state = {value:""}

  handleKeyPress = (e) => {
    if (e.key === 'Enter') {
      this.setState({value:e.target.value})
    }
  }

  render() {
    return (
      <section>
        <Input onKeyPress={this.handleKeyPress}/>
        <br/>
        <output>{this.state.value}</output>
      </section>
    );
  }
}

ReactDOM.render(
  <Form />,
  document.getElementById("react")
)
<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="react"></div>

onmyway133
fonte
5

Reagir usuários, aqui está uma resposta para a integridade.

Reagir versão 16.4.2

Você deseja atualizar para cada pressionamento de tecla ou obter o valor apenas no envio. Adicionar os principais eventos ao componente funciona, mas existem alternativas recomendadas nos documentos oficiais.

Componentes controlados vs não controlados

Controlada

No Documentos - Formulários e componentes controlados :

Em HTML, elementos de formulário como input, textarea e select normalmente mantêm seu próprio estado e o atualizam com base na entrada do usuário. Em React, o estado mutável geralmente é mantido na propriedade state dos componentes e atualizado apenas com setState ().

Podemos combinar os dois fazendo com que o estado React seja a “única fonte de verdade”. O componente React que renderiza um formulário também controla o que acontece nesse formulário nas entradas subsequentes do usuário. Um elemento do formulário de entrada cujo valor é controlado pelo React dessa maneira é chamado de "componente controlado".

Se você usar um componente controlado, precisará manter o estado atualizado para cada alteração no valor. Para que isso aconteça, você vincula um manipulador de eventos ao componente. Nos exemplos dos documentos, geralmente o evento onChange.

Exemplo:

1) Vincular manipulador de eventos no construtor (valor mantido no estado)

constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
}

2) Criar função de manipulador

handleChange(event) {
    this.setState({value: event.target.value});
}

3) Criar função de envio de formulário (o valor é obtido do estado)

handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
}

4) Renderizar

<form onSubmit={this.handleSubmit}>
    <label>
      Name:
      <input type="text" value={this.state.value} onChange={this.handleChange} />
    </label>
    <input type="submit" value="Submit" />
</form>

Se você usar componentes controlados , sua handleChangefunção será sempre acionada, a fim de atualizar e manter o estado adequado. O estado sempre terá o valor atualizado e, quando o formulário for enviado, o valor será retirado do estado. Isso pode ser um engodo se seu formulário for muito longo, porque você precisará criar uma função para cada componente ou escrever uma simples que lide com a alteração de valor de cada componente.

Descontrolado

No componente Documentos - Não controlado

Na maioria dos casos, recomendamos o uso de componentes controlados para implementar formulários. Em um componente controlado, os dados do formulário são manipulados por um componente React. A alternativa são componentes não controlados, nos quais os dados do formulário são manipulados pelo próprio DOM.

Para gravar um componente não controlado, em vez de gravar um manipulador de eventos para cada atualização de estado, você pode usar um ref para obter valores de formulário no DOM.

A principal diferença aqui é que você não usa a onChangefunção, mas onSubmita forma para obter os valores e validar se necessário.

Exemplo:

1) Ligue o manipulador de eventos e crie ref à entrada no construtor (nenhum valor mantido no estado)

constructor(props) {
    super(props);
    this.handleSubmit = this.handleSubmit.bind(this);
    this.input = React.createRef();
}

2) Criar função de envio de formulário (o valor é obtido do componente DOM)

handleSubmit(event) {
    alert('A name was submitted: ' + this.input.current.value);
    event.preventDefault();
}

3) Renderizar

<form onSubmit={this.handleSubmit}>
    <label>
      Name:
      <input type="text" ref={this.input} />
    </label>
    <input type="submit" value="Submit" />
</form>

Se você usar componentes não controlados , não há necessidade de vincular uma handleChangefunção. Quando o formulário é enviado, o valor será retirado do DOM e as validações necessárias podem ocorrer neste momento. Não há necessidade de criar funções de manipulador para nenhum dos componentes de entrada também.

Seu problema

Agora, para o seu problema:

... Quero que seja chamado quando pressionar 'Enter quando o número inteiro tiver sido inserido

Se você deseja conseguir isso, use um componente não controlado. Não crie os manipuladores do onChange se não for necessário. A enterchave enviará o formulário e a handleSubmitfunção será acionada.

Alterações que você precisa fazer:

Remova a chamada onChange do seu elemento

var inputProcent = React.CreateElement(bootstrap.Input, {type: "text",
    //    bsStyle: this.validationInputFactor(),
    placeholder: this.initialFactor,
    className: "input-block-level",
    // onChange: this.handleInput,
    block: true,
    addonBefore: '%',
    ref:'input',
    hasFeedback: true
});

Manipule o formulário, envie e valide sua entrada. Você precisa obter o valor do seu elemento na função de envio de formulário e validar. Certifique-se de criar a referência ao seu elemento no construtor.

  handleSubmit(event) {
      // Get value of input field
      let value = this.input.current.value;
      event.preventDefault();
      // Validate 'value' and submit using your own api or something
  }

Exemplo de uso de um componente não controlado:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    // bind submit function
    this.handleSubmit = this.handleSubmit.bind(this);
    // create reference to input field
    this.input = React.createRef();
  }

  handleSubmit(event) {
    // Get value of input field
    let value = this.input.current.value;
    console.log('value in input field: ' + value );
    event.preventDefault();
    // Validate 'value' and submit using your own api or something
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" ref={this.input} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

ReactDOM.render(
  <NameForm />,
  document.getElementById('root')
);
c-chavez
fonte
3

Você também pode escrever uma pequena função de invólucro como esta

const onEnter = (event, callback) => event.key === 'Enter' && callback()

Em seguida, consuma nas suas entradas

<input 
    type="text" 
    placeholder="Title of todo" 
    onChange={e => setName(e.target.value)}
    onKeyPress={e => onEnter(e, addItem)}/>
David Alsh
fonte