使用指令的 AngularJS 浏览器自动填充解决方法

2022-08-30 05:43:28

在AngularJS中提交表单并使用浏览器记住密码功能时,在随后的登录尝试中,您让浏览器使用用户名和密码填写登录表单,模型不会根据自动填充进行更改。$scope

我发现的唯一肮脏的黑客是使用以下指令:

app.directive("xsInputSync", ["$timeout" , function($timeout) {
    return {
        restrict : "A",
        require: "?ngModel",
        link : function(scope, element, attrs, ngModel) {
            $timeout(function() {
                if (ngModel.$viewValue && ngModel.$viewValue !== element.val()) {
                    scope.apply(function() {
                        ngModel.$setViewValue(element.val());
                    });
                }
                console.log(scope);
                console.log(ngModel.$name);
                console.log(scope[ngModel.$name]);
            }, 3000);
        }
    };
}]);

问题在于 不会根据返回值更改模型或视图。我怎样才能做到这一点?ngModel.$setViewValue(element.val());element.val()


答案 1

显然,这是Angular的一个已知问题,目前处于打开状态。

我不确定除了像你一样尝试的某种工作之外,你还能在这里做些什么。看来你走在正确的轨道上。我无法让我的浏览器尝试记住您的plunk密码,所以我不确定这是否有效,但请看一下:

app.directive('autoFillSync', function($timeout) {
   return {
      require: 'ngModel',
      link: function(scope, elem, attrs, ngModel) {
          var origVal = elem.val();
          $timeout(function () {
              var newVal = elem.val();
              if(ngModel.$pristine && origVal !== newVal) {
                  ngModel.$setViewValue(newVal);
              }
          }, 500);
      }
   }
});
<form name="myForm" ng-submit="login()">
   <label for="username">Username</label>
   <input type="text" id="username" name="username" ng-model="username" auto-fill-sync/><br/>
   <label for="password">Password</label>
   <input type="password" id="password" name="password" ng-model="password" auto-fill-sync/><br/>
   <button type="submit">Login</button>
</form>

我认为你只需要简化一下你的方法。我绝对推荐的一件事是检查并确保你没有覆盖一些糟糕的用户的输入。另外,3秒可能太长了。您不必在$timeout中调用$apply(),顺便说一句,它应该自动为您排队$digest。ngModel.$pristine

真正的问题:你的浏览器会打败Angular执行吗?我的浏览器呢?

这可能是一场无法取胜的战争,这就是为什么Angular(或Knockout)无法轻易解决它的原因。无法保证在指令初始执行时输入中的数据的状态。甚至在Angular初始化的时候也没有....所以这是一个棘手的问题。


答案 2

这是一个解决方案,它远不如其他解决方案那么笨拙,并且在语义上是合理的AngularJS:http://victorblog.com/2014/01/12/fixing-autocomplete-autofill-on-angularjs-form-submit/

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 autofilled 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>