javascript - ejemplos - poner el foco en un input jquery
Establecer el foco en la entrada después del renderizado (23)
¿Cuál es la forma de reaccionar de establecer el foco en un campo de texto en particular después de que se representa el componente?
La documentación parece sugerir el uso de referencias, por ejemplo:
Establecer
ref="nameInput"
en mi campo de entrada en la función de renderizado, y luego llamar:
this.refs.nameInput.getInputDOMNode().focus();
¿Pero a dónde debería llamar esto? He probado algunos lugares pero no puedo hacer que funcione.
Advertencia: ReactDOMComponent: No acceda a .getDOMNode () de un nodo DOM; en su lugar, use el nodo directamente. Este nodo DOM fue procesado por la
App
.
Debiera ser
componentDidMount: function () {
this.refs.nameInput.focus();
}
Centrarse en el monte
Si solo desea enfocar un elemento cuando se monta (inicialmente se procesa), se hará un uso simple del atributo autoFocus.
<input autoFocus type="text" />
Enfoque dinámico
para controlar el enfoque dinámicamente, use una función general para ocultar los detalles de implementación de sus componentes.
Reaccionar 16.8 + componente funcional - useFocus hook
componentDidMount() {
this.refs.linkInput.focus()
}
Luego úselo en cualquier componente funcional.
<input type="text" autoFocus />
Reaccionar 16.3 + Componentes de clase - utilizarFocus
const useFocus = () => {
const htmlElRef = useRef(null)
const setFocus = () => {htmlElRef.current && htmlElRef.current.focus()}
return [ setFocus, htmlElRef ]
}
Luego úsalo en cualquier componente de clase
const FocusDemo = () => {
const [value, setValue] = useState("")
const [setInputFocus, inputRef] = useFocus()
const [setBtnFocus, btnRef] = useFocus()
return (
<> {/* React.Fragment */}
<input
value={value}
onChange={(e)=>{
setValue(e.target.value)
if ( some logic ){ setBtnFocus() }
}}
ref={inputRef}
/>
<button
onClick={setInputFocus}
ref={btnRef}
>
Refocus
</button>
</>
)
}
Árbitro. Comentario de @ Dave sobre la respuesta de @ Dhiraj; una alternativa es usar la funcionalidad de devolución de llamada del atributo ref en el elemento que se está representando (después de que un componente se procesa primero):
<input ref={ function(component){ React.findDOMNode(component).focus();} } />
¿No necesitas
getInputDOMNode
?
en este caso...
Simplemente obtenga la
ref
y
focus()
cuando se monte el
componente
-
componentDidMount
...
import React from ''react'';
import { render } from ''react-dom'';
class myApp extends React.Component {
componentDidMount() {
this.nameInput.focus();
}
render() {
return(
<div>
<input ref={input => { this.nameInput = input; }} />
</div>
);
}
}
ReactDOM.render(<myApp />, document.getElementById(''root''));
Acabo de encontrarme con este problema y estoy usando react
15.0.1
15.0.2 y estoy usando la sintaxis ES6 y no obtuve lo que necesitaba de las otras respuestas desde que la v.15 cayó hace semanas y algunas de
this.refs
propiedades
this.refs
quedaron en desuso
y se
removed
.
En general, lo que necesitaba era:
- Enfoca el primer elemento de entrada (campo) cuando se monta el componente
- Enfoque el primer elemento de entrada (campo) con un error (después de enviar)
Estoy usando:
- Contenedor de reacción / Componente de presentación
- Redux
- React-Router
Enfocar el primer elemento de entrada
autoFocus={true}
en la primera
<input />
en la página para que cuando el componente se monte, obtenga el foco.
Enfoque el primer elemento de entrada con un error
Esto tomó más tiempo y fue más complicado. Estoy manteniendo fuera el código que no es relevante para la solución por brevedad.
Tienda Redux / Estado
Necesito un estado global para saber si debo establecer el foco y deshabilitarlo cuando se configuró, por lo que no vuelvo a configurar el foco cuando los componentes se vuelven a procesar (usaré
componentDidUpdate()
para verificar ajuste de enfoque.)
Esto podría diseñarse como mejor le parezca para su aplicación.
{
form: {
resetFocus: false,
}
}
Componente contenedor
El componente necesitará tener establecida la propiedad
resetfocus
y un callBack para borrar la propiedad si termina configurando el foco en sí mismo.
También tenga en cuenta que organicé mis Action Creators en archivos separados principalmente debido a que mi proyecto es bastante grande y quería dividirlos en trozos más manejables.
import { connect } from ''react-redux'';
import MyField from ''../presentation/MyField'';
import ActionCreator from ''../actions/action-creators'';
function mapStateToProps(state) {
return {
resetFocus: state.form.resetFocus
}
}
function mapDispatchToProps(dispatch) {
return {
clearResetFocus() {
dispatch(ActionCreator.clearResetFocus());
}
}
}
export default connect(mapStateToProps, mapDispatchToProps)(MyField);
Componente de presentación
import React, { PropTypes } form ''react'';
export default class MyField extends React.Component {
// don''t forget to .bind(this)
constructor(props) {
super(props);
this._handleRef = this._handleRef.bind(this);
}
// This is not called on the initial render so
// this._input will be set before this get called
componentDidUpdate() {
if(!this.props.resetFocus) {
return false;
}
if(this.shouldfocus()) {
this._input.focus();
this.props.clearResetFocus();
}
}
// When the component mounts, it will save a
// reference to itself as _input, which we''ll
// be able to call in subsequent componentDidUpdate()
// calls if we need to set focus.
_handleRef(c) {
this._input = c;
}
// Whatever logic you need to determine if this
// component should get focus
shouldFocus() {
// ...
}
// pass the _handleRef callback so we can access
// a reference of this element in other component methods
render() {
return (
<input ref={this._handleRef} type="text" />
);
}
}
Myfield.propTypes = {
clearResetFocus: PropTypes.func,
resetFocus: PropTypes.bool
}
Visión de conjunto
La idea general es que cada campo de formulario que podría tener un error y estar enfocado debe verificarse a sí mismo y si necesita establecer el enfoque en sí mismo.
Hay una lógica de negocios que debe suceder para determinar si el campo dado es el campo correcto para establecer el foco. Esto no se muestra porque dependerá de la aplicación individual.
Cuando se envía un formulario, ese evento debe establecer el indicador de foco global
resetFocus
en verdadero.
Luego, a medida que cada componente se actualice, verá que debe verificar para ver si obtiene el foco y, si lo hace, enviar el evento para restablecer el foco para que otros elementos no tengan que seguir revisando.
editar
Como nota al margen, tenía mi lógica de negocios en un archivo de "utilidades" y simplemente
shouldfocus()
el método y lo llamé dentro de cada método
shouldfocus()
.
¡Salud!
AutoFocus funcionó mejor para mí. Necesitaba cambiar algo de texto a una entrada con ese texto en doble clic, así que esto es lo que terminé con:
<input autoFocus onFocus={this.setCaretToEnd} value={this.state.editTodo.value} onDoubleClick={this.updateTodoItem} />
NOTA: Para solucionar el problema donde React coloca el cursor al comienzo del texto, use este método:
setCaretToEnd(event) {
var originalText = event.target.value;
event.target.value = '''';
event.target.value = originalText;
}
Encontrado aquí: https://coderwall.com/p/0iz_zq/how-to-put-focus-at-the-end-of-an-input-with-react-js
Dado que hay muchas razones para este error, pensé que también publicaría el problema que estaba enfrentando. Para mí, el problema era que representaba mis entradas como contenido de otro componente.
export default ({ Content }) => { return ( <div className="container-fluid main_container"> <div className="row"> <div className="col-sm-12 h-100"> <Content /> // I rendered my inputs here </div> </div> </div> ); }
Así es como llamé al componente anterior:
<Component Content={() => { return ( <input type="text"/> ); }} />
Debería hacerlo en
componentDidMount
y en su lugar la
refs callback
.
Algo como esto
componentDidMount(){
this.nameInput.focus();
}
class App extends React.Component{
componentDidMount(){
this.nameInput.focus();
}
render() {
return(
<div>
<input
defaultValue="Won''t focus"
/>
<input
ref={(input) => { this.nameInput = input; }}
defaultValue="will focus"
/>
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById(''app''));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.3.1/react-dom.js"></script>
<div id="app"></div>
Después de probar muchas opciones anteriores sin éxito, descubrí que fue como estaba
disabling
y luego
enabling
la entrada que causó que se perdiera el foco.
Tenía un accesorio que
sendingAnswer
una
sendingAnswer
que desactivaba la entrada mientras estaba sondeando el backend.
export default class DefaultRolesPage extends React.Component {
addRole = ev => {
ev.preventDefault();
const roleKey = this.roleKey++;
this::updateState({
focus: {$set: roleKey},
formData: {
roles: {
$push: [{
id: null,
name: '''',
permissions: new Set(),
key: roleKey,
}]
}
}
})
}
render() {
const {formData} = this.state;
return (
<GridForm onSubmit={this.submit}>
{formData.roles.map((role, idx) => (
<GridSection key={role.key}>
<GridRow>
<GridCol>
<label>Role</label>
<TextBox value={role.name} onChange={this.roleName(idx)} autoFocus={role.key === this.state.focus}/>
</GridCol>
</GridRow>
</GridSection>
))}
</GridForm>
)
}
}
Una vez que eliminé el accesorio deshabilitado, todo comenzó a funcionar nuevamente.
Esta es la forma correcta, cómo enfocar automáticamente.
Cuando usa la devolución de llamada en lugar de la cadena como valor de referencia, se llama automáticamente.
Tienes tu referencia disponible que sin la necesidad de tocar el DOM usando
getDOMNode
render: function() {
return <TextInput ref={(c) => this._input = c} />;
},
componentDidMount: function() {
this._input.focus();
},
Esta ya no es la mejor respuesta.
A partir de v0.13,
this.refs
puede no estar disponible hasta AFTER
componentDidMount()
, en algunos casos extraños.
Simplemente agregue la etiqueta de
autoFocus
a su campo de entrada, como FakeRainBrigand mostró arriba.
La respuesta de @ Dhiraj es correcta, y para su comodidad, puede usar el accesorio de enfoque automático para que una entrada se enfoque automáticamente cuando se monta:
<input autoFocus name=...
Tenga en cuenta que en jsx es
autoFocus
(mayúscula F) a diferencia del viejo html que no distingue entre mayúsculas y minúsculas.
La respuesta más simple es agregar ref = "algún nombre" en el elemento de texto de entrada y llamar a la siguiente función.
componentDidMount(){
this.refs.field_name.focus();
}
// here field_name is ref name.
<input type="text" ref="field_name" />
Los documentos de React ahora tienen una sección para esto. https://facebook.github.io/react/docs/more-about-refs.html#the-ref-callback-attribute
import React, { useEffect, useRef } from ''react'';
const MyForm = () => {
const textInput = useRef(null);
useEffect(() => {
textInput.current.focus();
}, []);
return (
<div>
<input ref={textInput} />
</div>
);
};
Para mover el foco a un elemento recién creado, puede almacenar la ID del elemento en el estado y usarlo para configurar el
autoFocus
.
p.ej
<Input
autoFocus={question}
placeholder={
gettingQuestion ? ''Loading...'' : ''Type your answer here...''
}
value={answer}
onChange={event => dispatch(updateAnswer(event.target.value))}
type="text"
autocomplete="off"
name="answer"
// disabled={sendingAnswer} <-- Causing focus to be lost.
/>
De esta manera, ninguno de los cuadros de texto se enfoca en la carga de la página (como quiero), pero cuando presiona el botón "Agregar" para crear un nuevo registro, ese nuevo registro se enfoca.
Dado que
autoFocus
no se "ejecuta" nuevamente a menos que el componente se vuelva a montar, no tengo que molestarme en desarmar
this.state.focus
(es decir, no seguirá robando el foco mientras actualizo otros estados).
Puede poner esa llamada al método dentro de la función de renderizado.
O dentro del método del ciclo de vida,
componentDidUpdate
React 16.3 agregó una nueva forma conveniente de manejar esto mediante la creación de una referencia en el constructor del componente y usarlo como a continuación:
render: function() {
return (
<TextInput
ref={function(input) {
if (input != null) {
input.focus();
}
}} />
);
},
Para más detalles, puede consultar este artículo en el blog React.
Actualizar:
A partir de React
16.8
,
useRef
hook se puede usar en componentes de función para lograr el mismo resultado:
class MyForm extends Component {
constructor(props) {
super(props);
this.textInput = React.createRef();
}
componentDidMount() {
this.textInput.current.focus(); // one important change here is that we need to access the element via current.
}
render() {
// instead of using arrow function, the created ref can be used directly.
return(
<div>
<input ref={this.textInput} />
</div>
);
}
}
Si solo desea realizar el enfoque automático en React, es simple.
const utilizeFocus = () => {
const ref = React.createRef()
const setFocus = () => {ref.current && ref.current.focus()}
return {setFocus, ref}
}
Mientras que si solo quiere saber dónde colocar ese código, la respuesta está en componentDidMount ().
v014.3
class App extends Component {
constructor(props){
super(props)
this.input1Focus = utilizeFocus()
this.BtnFocus = utilizeFocus()
}
render(){
return (
<> {/* React.Fragment */}
<input
value={value}
onChange={(e)=>{
setValue(e.target.value)
if ( some logic ){ this.BtnFocus.setFocus() }
}}
ref={this.input1Focus.ref}
/>
<button
onClick={this.input1Focus.setFocus()}
ref={this.BtnFocus.ref}
>
Refocus
</button>
</>
)
}
}
En la mayoría de los casos, puede adjuntar una referencia al nodo DOM y evitar el uso de findDOMNode.
Lea los documentos de la API aquí: https://facebook.github.io/react/docs/top-level-api.html#reactdom.finddomnode
Tenga en cuenta que ninguna de estas respuestas funcionó para mí con un componente material-ui TextField . Por ¿Cómo establecer el foco en un materialUI TextField? Tuve que saltar algunos aros para que esto funcione:
const focusUsernameInputField = input => {
if (input) {
setTimeout(() => {input.focus()}, 100);
}
};
return (
<TextField
hintText="Username"
floatingLabelText="Username"
ref={focusUsernameInputField}
/>
);
Tengo el mismo problema pero también tengo algo de animación, por lo que mi colega sugiere usar window.requestAnimationFrame
Este es el atributo ref de mi elemento:
ref={(input) => {input && window.requestAnimationFrame(()=>{input.focus()})}}
Versión actualizada puedes consultar aquí
componentDidMount() {
// Focus to the input as html5 autofocus
this.inputRef.focus();
}
render() {
return <input type="text" ref={(input) => { this.inputRef = input }} />
})
getRenderedComponent().props.input
casi toda la respuesta pero no vi un
getRenderedComponent().props.input
Configure sus referencias de entrada de texto
this.refs.username.getRenderedComponent().props.input.onChange('''');
A partir de React 0.15 , el método más conciso es:
<input ref={input => input && input.focus()}/>