AngularJS browser autofill workaround by using a directive

http://stackoverflow.com/questions/14965968/angularjs-browser-autofill-workaround-by-using-a-directive

Apparently this is a known issue with Angular and is currently open

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>

我的想法

印象中以前查的時候好像還沒有丟出這個 auto-fill-sync 的 directive,所以這次真的碰到要解決這個問題,我很快的想到應該實驗一下 browser 的 autofill 是不是真的會在 <input> 裡 fill 進東西。

如果只是 AngularJS 那邊沒有抓到 autofill 的動作,應該就還算好解決,只要想辦法通知 AngularJS 就好了。

怕是怕 browser 是直到你確定要送出前夕才塞入 autofill 的值,這樣誰也幫不了我了~~~

$('#username').val();
// output: "我的帳號"

好加在實驗結果是後者 (呼)

於是我寫了一個自己的版本(因為沒有先看 stackoverflow 那篇…)

/* file: autocomplete-fix.js */

app.directive('autocompleteFix', ['$timeout', '$log', function ($timeout, $log) {
  return {
    require: 'ngModel',
    restrict: 'A',
    link: function postLink(scope, iElm, iAttrs, ctrl) {
      /**
       * Delay for 450ms works for Chrome on OS X
       */
      var _delay = 450;

      if (iAttrs.autocompleteFix) {
        _delay = parseInt(iAttrs.autocompleteFix, 10);
      }

      $log.debug('delay', _delay);

      $timeout(function () {
        ctrl.$setViewValue(iElm.val());
      }, _delay);
    }
  };
}]);

有趣的地方是,_delay 在 300, 400 時,都會有機會沒通知到 AngularJS,所以我自己試的恰當值大約是 450(而 stackoverflow 上的是 500)。

感覺 stackoverflow 上的版本似乎考慮比較周到,所以就留個 gist 存著吧!