Angularjs Chrome autocomplete dilemma
Solution 1
From the link added in the comment: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);
}
}
}
}]);
Solution 2
From: Developer.mozilla.org docs Turning_off_form_autocompletion
If an author would like to prevent the auto-filling of password fields in user management pages where a user can specify a new password for someone other than themselves, autocomplete="new-password" should be specified, though support for this has not been implemented in all browsers yet.
So, what makes it work for me:
- set autocomplete="new-password" on the password field
- set autocomplete="off" in the username field.
I hope that it works for you too :)
Solution 3
As said here, https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
The Google Chrome UI for auto-complete requests varies, depending on whether autocomplete is set to off on input elements as well as their form. Specifically, when a form has autocomplete set to off and its input element's autocomplete field is not set, then if the user asks for autofill suggestions for the input element, Chrome might display a message saying "autocomplete has been disabled for this form." On the other hand, if both the form and the input element have autocomplete set to off, the browser will not display that message. For this reason, you should set autocomplete to off for each input that has custom auto-completion.
You need to set autocomplete="off" on both form
and input
I don't think this is related to AngularJS
Solution 4
I had the same issue and found a very simple solution that just uses jQuery to grab the value on submit. In my controller I have the following:
$scope.username = "";
$scope.password = "";
$scope.login = function(){
$scope.username = $("#username").val();
$scope.password = $("#password").val();
// Proceed as normal
};
There are some downsides, if you need to do validation etc but otherwise it's fine for smaller forms like this.
Solution 5
You could watch the email field value and everytime the value in that field is changing, you could trigger a "change"-event on the password field. This events trigger all the ng-model magic on that field and updates the model.
module.directive("autocompleteFor", function () {
return {
restrict: "A",
link: function ($scope, $element, $attrs) {
$scope.$watch($attrs.autocompleteFor, function () {
$element.triggerHandler("change");
})
}
}
});
With this directive you could handle that scenario like this:
<input type="email" name="email" ng-model="user.email">
<input type="password" autocomplete-for="user.email" name="password" ng-model="user.password" required>
-----------------------------
Comments
-
Catfish over 3 years
I have a simple login form which works just peachy unless you use Chrome's auto complete feature.
If you start typing and use the auto complete feature and it auto populates your password, my angularjs model does not have any value for the password.
I tried to turn autocomplete off by setting the attribute on the form
autocomplete="off"
but that doesn't seem to have any effect.How can I either: 1. Ensure that I can get the value if someone uses Chrome's auto-complete feature? 2. Disable Chrome's auto-complete feature?
<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>
-
Catfish over 10 yearsThe question is related to AngularJS in case there is a solution to capturing the auto-fill text in Angularjs. I was not aware of having to set autocomplete off on the input's though.
-
Catfish over 10 yearsI tried setting autocomplete="off" on both the form and the input elements and the auto complete is still autocompleting and the value still does not get set to my angular model.
-
Ryan Wheale over 10 years+1 This is the best solution on this page because it doesn't disable autocomptlete. Disabling autocomplete is like saying "hey user, screw you and your preferences". The only cross-browser solution is to poll. It's not difficult, and someone already wrote the angular-friendly code...
-
Christian about 10 yearsControllers actually should not have that kind of jquery code. Avoid accessing the DOM from there, thats why directives are there. This kind of code might break your testing code.
-
Dachande663 about 10 yearsAnd for anywhere else I'd agree with you. But this is a browser quirk that a headless phantomjs instance wouldn't pick up anyway.
-
beauXjames over 9 yearswould be nice...but nope...not consistent across the board
-
Eugene over 8 years
link.apply
throws error.ngModel
isn't passed through sincecompile
function doesn't accept it and therefore$setViewValue
doesn't work. -
anujeet over 7 yearsHi I'm new to angularjs, after adding the above code in js file and including it in the HTML file, I'm getting this error Uncaught Error: [$injector:nomod] errors.angularjs.org/1.4.8/$injector/nomod?p0=myApp Could you please help me out?
-
Luke over 7 yearsSad this doesn't work because even the Chrome notes here bugs.chromium.org/p/chromium/issues/detail?id=252609 say to use
autocomplete="off"
-
Luke over 7 yearson/off seem to be the HTML5 standard for the
autocomplete
property. w3.org/wiki/HTML/Elements/input/text -
Alex Klaus over 7 yearsIs it the best solution for Angular2 as well? It seems that when the user chooses a Chrome's suggestion to fill the form, the model doesn't pick up changes.
-
Campinho over 6 yearsI know the question was about angularjs. But why add code to fix the issue when you can add an attribute to the html?
-
andrea.rinaldi over 6 yearsand why should I work on validation in order to deal with autocompletion?
-
Cory Silva over 6 yearsI should have mentioned that this was a temporary fix while the bug existed in Chrome. It is no longer valid.
-
no id over 5 years> Note: ngForm cannot be used as a replacement for <form>, because it lacks its built-in HTML functionality. Specifically, you cannot submit ngForm like a <form> tag. That means, you cannot send data to the server with ngForm, or integrate it with ngSubmit. docs.angularjs.org/api/ng/directive/ngForm
-
Matej Janovčík over 5 yearsOf course you can send data to the server with ngForm, you just need to write custom logic, as you correctly mentioned it doesn't have built-in HTML form functionality