Angularjs Chrome自动完成困境

Cat*_*ish 38 javascript google-chrome autocomplete angularjs

我有一个简单的登录表单,除非你使用Chrome的自动完成功能,否则只能使用peachy.

如果您开始输入并使用自动完成功能并自动填充密码,则我的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>
Run Code Online (Sandbox Code Playgroud)

Pau*_*ice 21

从评论中添加的链接: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);
            }
        }
    }
}]);
Run Code Online (Sandbox Code Playgroud)

  • `link.apply`抛出错误.`ngModel`没有传递,因为`compile`函数不接受它,因此`$ setViewValue`不起作用. (4认同)
  • +1这是此页面上的最佳解决方案,因为它不会禁用autocomptlete.禁用自动填充就像是说"嘿用户,搞砸你和你的偏好".唯一的跨浏览器解决方案是进行民意调查.这并不困难,有人已经编写了角度友好代码...... (2认同)

ptg*_*amr 15

来自:Developer.mozilla.org docs Turning_off_form_autocompletion

如果作者想要阻止用户管理页面中自动填写密码字段,用户可以为自己以外的人指定新密码,则应指定autocomplete ="new-password",但是对此不支持已在所有浏览器中实现.

那么,是什么让它对我有用:

  • 在密码字段上设置autocomplete ="new-password"
  • 在用户名字段中设置autocomplete ="off".

我希望它也适合你:)


all*_*kim 11

如上所述,https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form

用于自动完成请求的Google Chrome用户界面会有所不同,具体取决于输入元素的自动填充功能是否设置为关闭以及表单.具体来说,当表单将自动完成设置为关闭并且未设置其输入元素的自动填充字段时,如果用户要求输入元素的自动填充建议,Chrome可能会显示一条消息,指出"此表单已禁用自动填充功能".另一方面,如果表单和输入元素都将自动完成设置为关闭,则浏览器将不显示该消息.因此,对于具有自定义自动完成功能的每个输入,您应将自动完成设置为关闭.

您需要在这两个设置自动完成="关闭" forminput

我不认为这与AngularJS有关

  • 我尝试在窗体和输入元素上设置autocomplete ="off",自动完成仍然是自动完成的,并且值仍然没有设置为我的角度模型. (2认同)

Dac*_*663 7

我遇到了同样的问题,发现了一个非常简单的解决方案,它只使用jQuery来获取提交的值.在我的控制器中,我有以下内容:

$scope.username = "";
$scope.password = "";

$scope.login = function(){
    $scope.username = $("#username").val();
    $scope.password = $("#password").val();
    // Proceed as normal
};
Run Code Online (Sandbox Code Playgroud)

有一些缺点,如果你需要进行验证等,但对于像这样的小型表格则没问题.

  • 而对于其他地方,我同意你的看法.但这是一个浏览器的怪癖,无头的phantomjs实例无论如何也无法接收. (5认同)
  • 控制器实际上不应该有那种jquery代码.避免从那里访问DOM,这就是指令的原因.这种代码可能会破坏您的测试代码. (2认同)