Este artículo fue traducido de: ¿Cómo establecer el foco en el campo de entrada?
¿Cuál es la "forma angular" para establecer el foco en el campo de entrada en AngularJS? ¿Cuál es la "forma angular" para establecer el foco en el campo de entrada en AngularJS ?
Requisitos más específicos: Requisitos más específicos:
- Cuando se abre un Modal , enfóquese en un predefinido
<input>
dentro de este Modal. Después de abrir una modalidad , concéntrese en el predefinido dentro de esta modalidad<input>
. - Cada
<input>
vez que sea visible (por ejemplo, haciendo clic en un botón), establezca el foco en él. Siempre que sea visible (por ejemplo, haciendo clic en algunos botones), establezca el foco en él .<input>
Traté de cumplir el primer requisito con autofocus
, pero esto funciona solo cuando el Modal se abre por primera vez, y solo en ciertos navegadores (por ejemplo, en Firefox no funciona). Traté de autofocus
cumplir el primer requisito , pero esto Solo funciona cuando se abre Modal por primera vez, y solo funciona en algunos navegadores (por ejemplo, no funciona en Firefox).
Cualquier ayuda será apreciada, cualquier ayuda será apreciada .
Piso # 1
Referencia: https://stackoom.com/question/10EpC/ Cómo establecer el foco en los campos de entrada
# 2F
- Cuando se abre un Modal, establezca el foco en un <input> predefinido dentro de este Modal. Después de abrir una modalidad, concéntrese en el <input> predefinido dentro de esta modalidad.
Defina una directiva y haga que $ mire una propiedad / disparador para que sepa cuándo enfocar el elemento: defina una directiva y haga que $ mire una propiedad / disparador para que sepa cuándo enfocar el elemento :
Name: <input type="text" focus-me="shouldBeOpen">
app.directive('focusMe', ['$timeout', '$parse', function ($timeout, $parse) {
return {
//scope: true, // optionally create a child scope
link: function (scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function (value) {
console.log('value=', value);
if (value === true) {
$timeout(function () {
element[0].focus();
});
}
});
// to address @blesh's comment, set attribute value to 'false'
// on blur event:
element.bind('blur', function () {
console.log('blur');
scope.$apply(model.assign(scope, false));
});
}
};
}]);
$ Timeout parece ser necesario para dar tiempo modal para renderizar. $ Timeout parece requerir el tiempo modal dado para renderizar.
'2.' '2. Cada vez que <input> sea visible (por ejemplo, haciendo clic en algún botón), establezca el foco en él. Siempre que <input> se vuelva visible (por ejemplo, haciendo clic en algún botón), establezca el foco en él .
Crea una directiva esencialmente como la de arriba Crea una directiva que sea básicamente similar a la de arriba . Algunos alcance Property Watch, y se convierte en Cuando verdadero (que se había marcado en su ng clic Handler), Ejecutar element[0].focus()
. Observar algún atributo alcance, cuando se convierte en verdadera (en el manipulador ng clic) se ejecuta element[0].focus()
. Dependiendo de su caso de uso, es posible que necesite o no un tiempo de espera de $ para este: Dependiendo de su caso de uso, puede o no necesitar un tiempo de espera de $:
<button class="btn" ng-click="showForm=true; focusInput=true">show form and
focus input</button>
<div ng-show="showForm">
<input type="text" ng-model="myInput" focus-me="focusInput"> {{ myInput }}
<button class="btn" ng-click="showForm=false">hide form</button>
</div>
app.directive('focusMe', function($timeout) {
return {
link: function(scope, element, attrs) {
scope.$watch(attrs.focusMe, function(value) {
if(value === true) {
console.log('value=',value);
//$timeout(function() {
element[0].focus();
scope[attrs.focusMe] = false;
//});
}
});
}
};
});
Actualización 7/2013 : He visto a algunas personas usar mis directivas de alcance de aislamiento original y luego tienen problemas con los campos de entrada incrustados (es decir, un campo de entrada en el modal) Actualización 7/2013 : He visto a algunas personas usarme La instrucción de rango de aislamiento original encontró problemas con el campo de entrada incrustado (es decir, el campo de entrada en el modal). Una directiva sin un nuevo alcance (o posiblemente un nuevo alcance infantil) debería aliviar algo del dolor. Una instrucción sin un nuevo alcance (o posiblemente un nuevo alcance infantil) debería aliviar algo del dolor. Así que arriba actualicé la respuesta para no usar ámbitos aislados. Así que arriba, actualicé la respuesta para no usar ámbitos aislados . A continuación se muestra la respuesta original: La siguiente es la respuesta original:
Respuesta original para 1., usando un alcance aislado: 1. Respuesta original para usar un alcance aislado :
Name: <input type="text" focus-me="{{shouldBeOpen}}">
app.directive('focusMe', function($timeout) {
return {
scope: { trigger: '@focusMe' },
link: function(scope, element) {
scope.$watch('trigger', function(value) {
if(value === "true") {
$timeout(function() {
element[0].focus();
});
}
});
}
};
});
Respuesta original para 2., usando un alcance aislado: 2. Respuesta original para usar un alcance aislado :
<button class="btn" ng-click="showForm=true; focusInput=true">show form and
focus input</button>
<div ng-show="showForm">
<input type="text" focus-me="focusInput">
<button class="btn" ng-click="showForm=false">hide form</button>
</div>
app.directive('focusMe', function($timeout) {
return {
scope: { trigger: '=focusMe' },
link: function(scope, element) {
scope.$watch('trigger', function(value) {
if(value === true) {
//console.log('trigger',value);
//$timeout(function() {
element[0].focus();
scope.trigger = false;
//});
}
});
}
};
});
Dado que necesitamos restablecer la propiedad trigger / focusInput en la directiva, '=' se usa para el enlace de datos bidireccional. Dado que necesitamos restablecer la propiedad trigger / focusInput en la directiva, "=" se usa para el enlace de datos bidireccional . En la primera directiva, '@' era suficiente, en la primera directiva, "@" es suficiente. También tenga en cuenta que cuando use '@', comparemos el valor de disparo con "verdadero" ya que @ siempre da como resultado una cadena. También tenga en cuenta que cuando use "@", comparemos el valor de disparo con "verdadero" porque @ siempre Producirá una cuerda.
Piso # 3
En primer lugar, de manera oficial que hacer es en el enfoque en el Plan de trabajo para 1.1 . En primer lugar, el método oficial enfoque es 1.1 de la hoja de ruta . Mientras tanto, puede escribir una directiva para implementar el enfoque de configuración. Al mismo tiempo, puede escribir una directiva para lograr el enfoque de configuración.
En segundo lugar, establecer el foco en un elemento después de que se haya vuelto visible actualmente requiere una solución alternativa. Segundo, para establecer el foco en el elemento actualmente visible, se necesita una solución. Simplemente retrase su llamada al elemento focus () con a $timeout
. Solo use $timeout
delay para llamar al elemento focus ()
Debido a que existe el mismo problema de controlador-modifica-DOM para el enfoque, desenfoque y selección, propongo tener una ng-target
directiva: dado que existe el mismo problema de controlador-modificado-DOM en foco, desenfoque y selección, sugiero usar la ng-target
directiva:
<input type="text" x-ng-model="form.color" x-ng-target="form.colorTarget">
<button class="btn" x-ng-click="form.colorTarget.focus()">do focus</button>
El hilo aquí Papel pintado Angular: http://goo.gl/ipsx4 , la escribió en su blog detalles aquí salvapantallas y mucho más: http://goo.gl/4rdZa aquí rosca de ángulo: HTTP : //goo.gl/ipsx4 , más detalles en Publicado aquí : http://goo.gl/4rdZa
Creará un acuerdo con la Directiva de la .focus()
función como responsable del tratamiento Dentro de su especificada por el ng-target
atributo. Las siguientes instrucciones ng-target
de crear un controlador interno propiedades especificadas .focus()
funciones. (Se crea una .blur()
y A .select()
DEMASIADO.) Demostración: http://jsfiddle.net/bseib/WUcQX/ (que .blur()
crea una .blur()
y una .select()
.) Demostración: HTTP : //jsfiddle.net/bseib/WUcQX/
# 4F
He escrito una directiva de enfoque vinculante bidireccional, al igual que el modelo recientemente. Escribí una directiva de enfoque vinculante bidireccional, como el modelo más reciente.
Puede usar la directiva de enfoque de esta manera: Puede usar la directiva de enfoque de esta manera :
<input focus="someFocusVariable">
Si realiza alguna variable de alcance de FocusVariable true
en cualquier parte de su controlador, la entrada se enfocará. Si realiza alguna variable de alcance de FocusFariable en cualquier posición del controlador true
, la entrada se convertirá en el foco. Y si desea "desenfocar" su entrada, someFocusVariable se puede establecer en falso. Y, si desea "desenfocar" la entrada, puede establecer someFocusVariable en falso. Es como la primera respuesta de Mark Rajcok pero con enlace bidireccional, como la primera respuesta de Mark Rajcok, pero con enlace bidireccional .
Aquí está la directiva: Esta es la directiva:
function Ctrl($scope) {
$scope.model = "ahaha"
$scope.someFocusVariable = true; // If you want to focus initially, set this to true. Else you don't need to define this at all.
}
angular.module('experiement', [])
.directive('focus', function($timeout, $parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
scope.$watch(attrs.focus, function(newValue, oldValue) {
if (newValue) { element[0].focus(); }
});
element.bind("blur", function(e) {
$timeout(function() {
scope.$apply(attrs.focus + "=false");
}, 0);
});
element.bind("focus", function(e) {
$timeout(function() {
scope.$apply(attrs.focus + "=true");
}, 0);
})
}
}
});
Uso: Uso:
<div ng-app="experiement">
<div ng-controller="Ctrl">
An Input: <input ng-model="model" focus="someFocusVariable">
<hr>
<div ng-click="someFocusVariable=true">Focus!</div>
<pre>someFocusVariable: {{ someFocusVariable }}</pre>
<pre>content: {{ model }}</pre>
</div>
</div>
Aquí está el violín: Este es el violín:
http://fiddle.jshell.net/ubenzer/9FSL4/8/ http://fiddle.jshell.net/ubenzer/9FSL4/8/
# 5F
(EDITAR: he agregado una solución actualizada debajo de esta explicación) (EDITAR: agregué una solución actualizada debajo de esta explicación )
Mark Rajcok es el hombre ... y su respuesta es una respuesta válida, pero
ha
tenido un defecto (lo siento Mark) ... Mark Rajcok es esta persona ... su respuesta es válida la respuesta, pero
hay
defectos (Marcar lo siento) ...
... Intente usar el booleano para enfocar la entrada, luego desenfoque la entrada, luego intente usarla para enfocar la entrada nuevamente
... Intente usar el booleano
para enfocar la entrada, luego desenfoque la entrada, luego intente
usarla Enfoca la entrada de nuevo.
No funcionará a menos que restablezca el valor booleano a falso, luego $ digest, luego lo restablezca a verdadero. No funcionará a menos que restablezca el valor booleano a falso y luego restablezca
$ digest a verdadero.
Incluso si usa una comparación de cadenas en su expresión, se verá obligado a cambiar la cadena a otra cosa, $ digest, luego volver a cambiarla. Incluso si usa la comparación de cadenas en la expresión,
tendrá que cambiar la cadena A $ digest, y luego cámbielo.
(Esto se ha abordado con el controlador de eventos de desenfoque). (Esto se ha abordado con el controlador de eventos de desenfoque ).
Por lo tanto, propongo esta solución alternativa: por lo tanto, propongo esta solución alternativa :
Use un evento, la característica olvidada de Angular Use un evento, la característica olvidada de Angular .
JavaScript ama los eventos después de todo. JavaScript ama los eventos después de todo . Los eventos están inherentemente acoplados de manera flexible, y aún mejor, evitas agregar otro $ watch a tu $ digest. Los eventos están inherentemente sueltos de acoplamiento, y aún mejor, evitas agregar otro $ watch en $ digest.
app.directive('focusOn', function() {
return function(scope, elem, attr) {
scope.$on(attr.focusOn, function(e) {
elem[0].focus();
});
};
});
Entonces ahora puedes usarlo así: Ahora puedes usarlo así :
<input type="text" focus-on="newItemAdded" />
y luego en cualquier lugar de tu aplicación ... y luego en cualquier lugar de tu aplicación ...
$scope.addNewItem = function () {
/* stuff here to add a new item... */
$scope.$broadcast('newItemAdded');
};
Esto es increíble porque puedes hacer todo tipo de cosas con algo como esto. Esto es genial porque puedes hacer todo tipo de cosas con tales cosas. Por un lado, puede vincular los eventos que ya existen. Primero, puede vincular los eventos que ya existen . Por otra parte, comienzas a hacer algo inteligente al hacer que diferentes partes de tu aplicación publiquen eventos a los que otras partes de tu aplicación pueden suscribirse. Por otro lado, puedes permitir que otras partes de la aplicación publiquen eventos permitiendo diferentes partes de la aplicación Suscríbase para comenzar a hacer cosas inteligentes.
De todos modos, este tipo de cosas me grita "impulsado por un evento. De todos modos, este tipo de cosas es un grito" impulsado por un evento "para mí. Creo que, como desarrolladores de Angular, nos esforzamos mucho para clavar clavijas con forma de telescopio en agujeros con forma de evento. Creo que, como desarrolladores de Angular, trabajamos muy duro para martillar clavos con forma de telescopio en agujeros con forma de evento.
¿Es la mejor solución? ¿Es la mejor solución ? No lo sé , no lo sé. Es una solución, es una solución.
Solución actualizado solución de actualización
Después del comentario de @ ShimonRachlenko a continuación, he cambiado ligeramente mi método de hacer esto. Después de que @ShimonRachlenko comentó a continuación, he cambiado ligeramente el método de hacer esto . Ahora uso una combinación de un servicio y una directiva que maneja un evento "detrás de escena": Ahora, uso una combinación de un servicio y una directiva para manejar "detrás de escena":
Aparte de eso, es el mismo director descrito anteriormente, además de eso, es el mismo director descrito anteriormente .
Aquí hay una demostración rápida Plunk
uso uso
<input type="text" focus-on="focusMe"/>
app.controller('MyCtrl', function($scope, focus) {
focus('focusMe');
});
Recursos fuente
app.directive('focusOn', function() {
return function(scope, elem, attr) {
scope.$on('focusOn', function(e, name) {
if(name === attr.focusOn) {
elem[0].focus();
}
});
};
});
app.factory('focus', function ($rootScope, $timeout) {
return function(name) {
$timeout(function (){
$rootScope.$broadcast('focusOn', name);
});
}
});
Piso # 6
También puede usar la función jqlite incorporada de angular.
angular.element('.selector').trigger('focus');