Дилемма автокомпонентов Chrome Angularjs
У меня есть простая форма входа в систему, которая работает просто peachy, если вы не используете функцию автообновления Chrome.
Если вы начнете печатать и использовать функцию автозаполнения, и она автоматически заполняет ваш пароль, моя модель angularjs не имеет никакого значения для пароля.
Я попытался отключить автозаполнение, установив атрибут в форме autocomplete="off"
, но это не имеет никакого эффекта.
Как я могу:
1. Убедитесь, что я могу получить значение, если кто-то использует функцию автозаполнения Chrome?
2. Отключить функцию автообновления 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>
Ответы
Ответ 1
Из ссылки, добавленной в комментарий: Проблема Github
// Due to browsers issue, it 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);
}
}
}
}]);
Ответ 2
Как сказано здесь, https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form
Пользовательский интерфейс Google Chrome для автозаполнения запросов зависит от будет ли автозаполнение отключено на входных элементах, а также их форма. В частности, когда форма имеет автозаполнение, установленное на поле автозаполнения входного элемента не установлено, тогда, если пользователь запрашивает для предложений автозаполнения для элемента ввода, Chrome может отображать сообщение "autocomplete был отключен для этой формы". На с другой стороны, если и форма, и входной элемент имеют автозаполнение выключено, браузер не отобразит это сообщение. Для этого причине, вы должны отключить автозаполнение для каждого входа, который пользовательское автозаполнение.
Вам нужно установить autocomplete = "off" на form
и input
Я не думаю, что это связано с AngularJS
Ответ 3
От: Developer.mozilla.org docs Turning_off_form_autocompletion
Если автор хотел бы предотвратить автоматическое заполнение полей пароля на страницах управления пользователями, где пользователь может указать новый пароль для кто-то другой, кроме себя, autocomplete = "new-password" должен быть но поддержка для этого не была реализована во всех браузеров.
Итак, что заставляет это работать для меня:
- установить autocomplete = "new-password" в поле пароля
- установить autocomplete = "off" в поле имени пользователя.
Я надеюсь, что это сработает и для вас:)
Ответ 4
У меня была такая же проблема, и я нашел очень простое решение, которое просто использует jQuery для захвата значения для submit. В моем контроллере у меня есть следующее:
$scope.username = "";
$scope.password = "";
$scope.login = function(){
$scope.username = $("#username").val();
$scope.password = $("#password").val();
// Proceed as normal
};
Есть некоторые недостатки, если вам нужно выполнить проверку и т.д., но в противном случае это отлично подходит для небольших форм, подобных этому.
Ответ 5
Вы можете посмотреть значение поля электронной почты, и каждый раз, когда значение в этом поле изменяется, вы можете вызвать "изменение" -эвен в поле пароля. Эти события запускают все магии ng-модели в этом поле и обновляют модель.
module.directive("autocompleteFor", function () {
return {
restrict: "A",
link: function ($scope, $element, $attrs) {
$scope.$watch($attrs.autocompleteFor, function () {
$element.triggerHandler("change");
})
}
}
});
С помощью этой директивы вы можете обработать этот сценарий следующим образом:
<input type="email" name="email" ng-model="user.email">
<input type="password" autocomplete-for="user.email" name="password" ng-model="user.password" required>
-----------------------------
Ответ 6
Чтобы отключить автозаполнение/автозаполнение от ввода, просто введите:
- autocomplete = "false" вместо autocomplete = "off"!
Ответ 7
Ниже директива работала для меня. Это простое и чистое исправление. Надеюсь, что это поможет!
Ссылка: Обходной способ обозревателя браузера AngularJS с использованием директивы
Вот решение, которое намного менее хакерское, чем другие представленные решения, и семантически звучит. 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);
}
};
});
Затем вы просто присоединяете директиву к своей форме:
<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>
Ответ 8
--- НЕ ДОЛЖНО СООТВЕТСТВУЕТ ---
Мне удалось отключить автозаполнение (достаточно странно), добавив следующее.
<form ... novalidate>
<input ... formnovalidate />
Ссылка на этот Plunker
Ответ 9
Мое решение для Chrome 35.0, Firefox 30.0, angular 1.2.18 (страница входа с паролем, автозаполнение, метод angular и перенаправление):
Как браузер знает, когда запрашивать пользователя для сохранения пароля?
Ответ 10
Старый вопрос, но что угодно
Я столкнулся с той же проблемой, и у меня есть небольшое "взломанное" решение. Эта проблема произошла во многих разных местах моего приложения, поэтому я создал директиву для повторного использования.
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"
});
}
}
}
]);
И просто добавьте
<fake-autocomplete></fake-autocomplete>
В начале вашей формы и браузер обнаружит поддельные поля как те, которые должны автозаполняться. Просто размещение display:none
в полях также больше не работает, я его протестировал.
Ответ 11
В моем случае я устанавливаю свойство autocomplete = "off" в форме и вводе.
<form autocomplete="off">
<input type="text" autocomplete="off">
</form>
Ответ 12
Это может быть гораздо более простое решение проблемы.
- Angularjs не может "видеть" значение
- Возьмите значение через DOM (jQuery), затем верните его в 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;
});
}
};
});
`` `