javascript - off - Angularjs Chrome autocompletar dilema
autocomplete off (12)
Tengo un formulario de inicio de sesión simple que funciona solo en color de rosa a menos que use la función de autocompletar de Chrome.
Si comienza a escribir y utiliza la función de autocompletar y rellena automáticamente su contraseña, mi modelo angularjs no tiene ningún valor para la contraseña.
Intenté desactivar el autocompletado configurando el atributo en el formulario autocomplete="off"
pero eso no parece tener ningún efecto.
¿Cómo puedo: 1. Asegurarme de que puedo obtener el valor si alguien utiliza la función de autocompletar de Chrome? 2. ¿Inhabilitar la función de autocompletar de Chrome?
<form class="form-signin" name="form" ng-submit="login()" autocomplete="off">
<h3>Login</h3>
<input type="email" name="email" class="form-control" placeholder="Email address" ng-model="user.email" required autofocus>
<input type="password" name="password" class="form-control" placeholder="Password" ng-model="user.password" required>
<button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
</form>
--- YA NO ES RELEVANTE ---
Pude desactivar la función de autocompletar (lo suficientemente extraño) añadiendo lo siguiente.
<form ... novalidate>
<input ... formnovalidate />
Como se dijo aquí, https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
La interfaz de usuario de Google Chrome para solicitudes de autocompletar varía, dependiendo de si la función de autocompletar está desactivada en los elementos de entrada, así como en su forma. Específicamente, cuando un formulario tiene el autocompletar desactivado y el campo de autocompletar de su elemento de entrada no está configurado, entonces si el usuario solicita autocompletar sugerencias para el elemento de entrada, Chrome podría mostrar un mensaje que dice "autocompletar ha sido deshabilitado para este formulario". Por otro lado, si tanto el formulario como el elemento de entrada tienen el autocompletar desactivado, el navegador no mostrará ese mensaje. Por esta razón, debe configurar la función de autocompletar para cada entrada que tenga una finalización automática personalizada.
Necesita configurar autocompletar = "apagado" tanto en la form
como en la input
No creo que esto esté relacionado con AngularJS
De: Developer.mozilla.org docs Turning_off_form_autocompletion
Si un autor desea evitar el llenado automático de campos de contraseña en páginas de administración de usuarios donde un usuario puede especificar una nueva contraseña para alguien que no sea él mismo, debe especificarse autocomplete = "new-password", aunque no se ha admitido esto. implementado en todos los navegadores aún.
Entonces, ¿qué hace que funcione para mí?
- establecer autocomplete = "new-password" en el campo de contraseña
- establecer autocompletar = "off" en el campo de nombre de usuario.
Espero que te funcione también :)
Del enlace agregado en el comentario: Github Issue''s
// Due to browsers issue, it''s impossible to detect without a timeout any changes of autofilled inputs
// https://github.com/angular/angular.js/issues/1460
// https://github.com/angular/angular.js/issues/1460#issuecomment-28662156
// Could break future Angular releases (if use `compile()` instead of `link())
// TODO support select
angular.module("app").config(["$provide", function($provide) {
var inputDecoration = ["$delegate", "inputsWatcher", function($delegate, inputsWatcher) {
var directive = $delegate[0];
var link = directive.link;
function linkDecoration(scope, element, attrs, ngModel){
var handler;
// By default model.$viewValue is equals to undefined
if(attrs.type == "checkbox"){
inputsWatcher.registerInput(handler = function(){
var value = element[0].checked;
// By default element is not checked
if (value && ngModel.$viewValue !== value) {
ngModel.$setViewValue(value);
}
});
}else if(attrs.type == "radio"){
inputsWatcher.registerInput(handler = function(){
var value = attrs.value;
// By default element is not checked
if (element[0].checked && ngModel.$viewValue !== value) {
ngModel.$setViewValue(value);
}
});
}else{
inputsWatcher.registerInput(handler = function(){
var value = element.val();
// By default value is an empty string
if ((ngModel.$viewValue !== undefined || value !== "") && ngModel.$viewValue !== value) {
ngModel.$setViewValue(value);
}
});
}
scope.$on("$destroy", function(){
inputsWatcher.unregisterInput(handler);
});
// Exec original `link()`
link.apply(this, [].slice.call(arguments, 0));
}
// Decorate `link()` don''t work for `inputDirective` (why?)
/*
directive.link = linkDecoration;
*/
// So use `compile()` instead
directive.compile = function compile(element, attrs, transclude){
return linkDecoration;
};
delete directive.link;
return $delegate;
}];
$provide.decorator("inputDirective", inputDecoration);
$provide.decorator("textareaDirective", inputDecoration);
//TODO decorate selectDirective (see binding "change" for `Single()` and `Multiple()`)
}]).factory("inputsWatcher", ["$interval", "$rootScope", function($interval, $rootScope){
var INTERVAL_MS = 500;
var promise;
var handlers = [];
function execHandlers(){
for(var i = 0, l = handlers.length; i < l; i++){
handlers[i]();
}
}
return {
registerInput: function registerInput(handler){
if(handlers.push(handler) == 1){
promise = $interval(execHandlers, INTERVAL_MS);
}
},
unregisterInput: function unregisterInput(handler){
handlers.splice(handlers.indexOf(handler), 1);
if(handlers.length == 0){
$interval.cancel(promise);
}
}
}
}]);
En mi caso, configuro la propiedad autocomplete = "off" en forma y entrada.
<form autocomplete="off">
<input type="text" autocomplete="off">
</form>
Mi solución para Chrome 35.0, Firefox 30.0, angular 1.2.18 (página de inicio de sesión con administrador de contraseñas, autocompletar, método angular y redirección):
¿Cómo sabe el navegador cuándo solicitarle al usuario que guarde la contraseña?
Para desactivar el autocompletar / autocompletar desde una entrada, simplemente escriba: - autocomplete = "false" en lugar de autocomplete = "off"!
Podría ser una solución mucho más simple al problema.
- Angularjs no pudo "ver" el valor
- Tome el valor a través de DOM (jQuery) y luego vuelva a ponerlo en Angularjs.
`` `
angular.module(''someModule'').directive(''chromeAutofillHack'', function()
{
return {
require: ''^ngModel'',
restrict: ''A'',
priority: 500, // set higher priority then other custom directives
link: function(scope, element, attrs , ngModelCtrl)
{
ngModelCtrl.$parsers.unshift(function(email)
{
if (!email) { // only do this when angular think there is no value
email = $(element).val();
ngModel.$setViewValue(email);
}
return email;
});
}
};
});
`` `
Puede ver el valor del campo de correo electrónico y cada vez que cambia el valor en ese campo, puede desencadenar un evento de "cambio" en el campo de contraseña. Este evento activa toda la magia ng-model en ese campo y actualiza el modelo.
module.directive("autocompleteFor", function () {
return {
restrict: "A",
link: function ($scope, $element, $attrs) {
$scope.$watch($attrs.autocompleteFor, function () {
$element.triggerHandler("change");
})
}
}
});
Con esta directiva, podrías manejar ese escenario de esta manera:
<input type="email" name="email" ng-model="user.email">
<input type="password" autocomplete-for="user.email" name="password" ng-model="user.password" required>
-----------------------------
Tuve el mismo problema y encontré una solución muy simple que solo usa jQuery para obtener el valor de enviar. En mi controlador tengo lo siguiente:
$scope.username = "";
$scope.password = "";
$scope.login = function(){
$scope.username = $("#username").val();
$scope.password = $("#password").val();
// Proceed as normal
};
Hay algunas desventajas, si necesita hacer la validación, etc., pero de lo contrario está bien para formularios más pequeños como este.
Una vieja pregunta, pero sea lo que sea
Me encontré con el mismo problema y tengo una pequeña solución de "pirateo". Este problema ocurrió en muchos lugares diferentes en mi aplicación, así que creé una directiva para reutilizar.
module.directive("fakeAutocomplete", [
function () {
return {
restrict: "EA",
replace: true,
template: "<div><input/><input type=/"password/"/></div>",
link: function (scope, elem, attrs) {
elem.css({
"overflow": "hidden",
"width": "0px",
"height": "0px"
});
}
}
}
]);
Y simplemente agrega
<fake-autocomplete></fake-autocomplete>
Al comienzo de su formulario y el navegador detectará los campos falsos como los que deben autocompletarse. Simplemente display:none
en los campos tampoco parece funcionar, lo he probado.
Debajo de la directiva funcionó para mí. Es una solución simple y limpia. ¡Espero que ayude!
Ref .: solución de autocompletar de navegador AngularJS mediante el uso de una directiva
Aquí hay una solución que es mucho menos hacky que otras soluciones presentadas y es semánticamente sólida AngularJS: VictorBlog.com
myApp.directive(''formAutofillFix'', function() {
return function(scope, elem, attrs) {
// Fixes Chrome bug: https://groups.google.com/forum/#!topic/angular/6NlucSskQjY
elem.prop(''method'', ''POST'');
// Fix autofill issues where Angular doesn''t know about auto-filled inputs
if(attrs.ngSubmit) {
setTimeout(function() {
elem.unbind(''submit'').submit(function(e) {
e.preventDefault();
elem.find(''input, textarea, select'').trigger(''input'').trigger(''change'').trigger(''keydown'');
scope.$apply(attrs.ngSubmit);
});
}, 0);
}
};
});
Luego, simplemente adjunte la directiva a su formulario:
<form ng-submit="submitLoginForm()" form-autofill-fix>
<div>
<input type="email" ng-model="email" ng-required />
<input type="password" ng-model="password" ng-required />
<button type="submit">Log In</button>
</div>
</form>