Giải pháp tự động điền trình duyệt AngularJS bằng cách sử dụng chỉ thị


111

Khi gửi biểu mẫu trong AngularJS và sử dụng chức năng ghi nhớ mật khẩu của trình duyệt, và trong lần đăng nhập tiếp theo, bạn để trình duyệt điền vào biểu mẫu đăng nhập bằng tên người dùng và mật khẩu, $scopemô hình sẽ không bị thay đổi dựa trên tự động điền.

Cách hack bẩn duy nhất mà tôi tìm thấy là sử dụng lệnh sau:

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);
        }
    };
}]);

Vấn đề là ngModel.$setViewValue(element.val()); không thay đổi mô hình cũng như chế độ xem dựa trên element.val()giá trị trả về. Làm thế nào tôi có thể thực hiện điều đó?


Đoạn mã này thoạt nhìn có vẻ ổn ... nhưng phần còn lại (đánh dấu, v.v.) ở đâu? Bạn có một trò đùa hay một trò đùa mà chúng tôi có thể thấy?
Ben Lesh

Đây là plunk: plnkr.co/edit/CHrBAVU9Ycl2ex2DRr6R Tôi không chắc liệu nó có hoạt động trực tiếp trên plunker hay không vì nó chạy trong iframe.
lucassp 19/02/13

1
Bạn không cần phải mở rộng phạm vi. $ Áp dụng bên trong $ timeout của góc. Bạn có thể cần nó bên trong native window.setTimeout. Nhưng tốt hơn hết là bạn nên sử dụng góc cạnh.
gorpacrate

1
Có một bản sửa lỗi polyfill "chính thức" từ Angular dev tbosch cho sự cố này. Vui lòng xem chi tiết trong câu trả lời stackoverflow.com/a/25687396/3009639 bên dưới.
orszaczky

Thật không may, bản sửa lỗi "chính thức" là phần mềm bỏ rơi và không hoạt động trên nhiều trình duyệt. Các vấn đề đã được nộp nhưng không được giải quyết nên việc tìm kiếm vẫn tiếp tục ...
cyberwombat

Câu trả lời:


45

Rõ ràng đây là một vấn đề đã biết với Angular và hiện đang mở

Tôi không chắc bạn có thể làm gì ở đây ngoài một số công việc xung quanh như bạn đang cố gắng. Có vẻ như bạn đang đi đúng hướng. Tôi không thể khiến trình duyệt của mình cố gắng nhớ mật khẩu cho plunk của bạn, vì vậy tôi không chắc liệu điều này có hoạt động hay không nhưng hãy xem:

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>

Tôi nghĩ bạn chỉ cần đơn giản hóa cách tiếp cận của mình một chút. Một điều tôi chắc chắn khuyên bạn nên kiểm trangModel.$pristine và đảm bảo rằng bạn không ghi đè dữ liệu nhập của một số người dùng kém. Ngoài ra, 3 giây có lẽ là quá dài. Bạn không cần phải gọi $ apply () trong thời gian chờ $, BTW, nó sẽ tự động xếp hàng một thông báo $ cho bạn.

Bí quyết thực sự: Liệu trình duyệt của bạn có đánh bại Angular để thực thi không? Còn về trình duyệt của tôi?

Đây có lẽ là một cuộc chiến bất khả kháng, đó là lý do tại sao Angular (hoặc Knockout) không thể giải quyết nó một cách dễ dàng. Không có gì đảm bảo về trạng thái của dữ liệu trong đầu vào của bạn tại thời điểm thực thi ban đầu của chỉ thị. Ngay cả tại thời điểm khởi tạo Angular .... Vì vậy, đó là một vấn đề khó giải quyết.


1
Điểm tốt về $ nguyên sơ. Chà, 3 giây chỉ dành cho mục đích thử nghiệm. Hộp thoại "Lưu mật khẩu" dường như hoạt động trên Safari. Đó là một vấn đề khác mà tôi phải điều tra.
lucassp 19/02/13

Chỉ cần đánh lừa anh ta với bộ nhớ cục bộ. :) ... Tôi sẽ tiếp tục suy nghĩ về nó. Nhưng tôi nghi ngờ về tính khả thi của việc tự động điền hoạt động với bất kỳ ràng buộc hai chiều nào.
Ben Lesh

Có, nhưng tôi vẫn cần có thể cập nhật mô hình từ chỉ thị để nó hoạt động.
lucassp

1
Tôi đã đùa về localStorage, bạn sẽ không muốn giữ mật khẩu ở đó.
Ben Lesh

1
Điều này sẽ không hoạt động với Safari và tính năng tự động điền thẻ tín dụng, vì tính năng tự động điền này được người dùng kích hoạt bất kỳ lúc nào
Dallas Clark

35

Đây là một giải pháp ít hack hơn nhiều so với các giải pháp khác được trình bày và có ngữ nghĩa 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);
    }
  };
});

Sau đó, bạn chỉ cần đính kèm chỉ thị vào biểu mẫu của mình:

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

2
Cái này đã hoạt động. Chúng tôi đã thử hầu hết các cách trên mà không có kết quả. Cảm ơn!!! Kết quả là trên mobbr.com
Patrick Savalle

1
Vì điều này sử dụng jQuery, nó sẽ không hoạt động nếu không có jQuery.
Quinn Strahl

1
Đây là năm 2018 và đây vẫn là bản sửa lỗi. Cảm ơn Ezekiel!
Scott Manny

35

Bạn không cần phải sử dụng một $timeouthoặc bất cứ thứ gì tương tự. Bạn có thể sử dụng một hệ thống sự kiện.

Tôi nghĩ rằng nó có nhiều góc cạnh hơn và không phụ thuộc vào jQuery hoặc bắt sự kiện tùy chỉnh.

Ví dụ trên trình xử lý gửi của bạn:

$scope.doLogin = function() {
    $scope.$broadcast("autofill:update");

    // Continue with the login.....
};

Và sau đó bạn có thể có một autofillchỉ thị như sau:

.directive("autofill", function () {
    return {
        require: "ngModel",
        link: function (scope, element, attrs, ngModel) {
            scope.$on("autofill:update", function() {
                ngModel.$setViewValue(element.val());
            });
        }
    }
});

Cuối cùng, HTML của bạn sẽ giống như sau:

<input type="text" name="username" ng-model="user.id" autofill="autofill"/>

14
Trong trường hợp của tôi, nút gửi bị tắt khi đầu vào trống.
gorpacrate

4
bạn không bao giờ gặp khó khăn với điều này vì nó không đồng bộ? nơi mà lệnh gọi đăng nhập đến máy chủ đã rời khỏi trước khi sự kiện được sao chép và chỉ thị có thời gian để cập nhật phạm vi?
Sander

12

Không cần phải hack nữa! Angular dev tbosch đã tạo một polyfill kích hoạt sự kiện thay đổi khi trình duyệt thay đổi các trường biểu mẫu mà không kích hoạt sự kiện thay đổi:

https://github.com/tbosch/autofill-event

Hiện tại, họ sẽ không xây dựng điều này vào mã Angular, vì đây là một bản sửa lỗi cho trình duyệt và cũng hoạt động mà không có Angular (ví dụ: đối với các ứng dụng jQuery thuần túy).

"Polyfill sẽ kiểm tra các thay đổi khi tải tài liệu và cả khi còn lại một đầu vào (chỉ ở cùng một biểu mẫu). Tuy nhiên, bạn có thể kích hoạt kiểm tra theo cách thủ công nếu muốn.

Dự án có các bài kiểm tra đơn vị cũng như các bài kiểm tra bán tự động, vì vậy cuối cùng chúng tôi đã có một nơi để thu thập tất cả các trường hợp sử dụng khác nhau cùng với các cài đặt trình duyệt được yêu cầu.

Xin lưu ý: Polyfill này hoạt động với các ứng dụng AngularJS thuần túy, với các ứng dụng AngularJS / jQuery nhưng cũng với các ứng dụng jQuery thuần túy không sử dụng Angular. "

Nó có thể được cài đặt với:

bower install autofill-event --save

Thêm tập lệnh autofill-event.js sau jQuery hoặc Angular vào trang của bạn.

Điều này sẽ làm như sau:

  • sau DOMContentLoaded: kiểm tra tất cả các trường đầu vào
  • một trường còn lại: kiểm tra tất cả các trường khác trong cùng một biểu mẫu

API (để kích hoạt kiểm tra theo cách thủ công):

  • $el.checkAndTriggerAutoFillEvent(): Thực hiện kiểm tra tất cả các phần tử DOM trong phần tử jQuery / jQLite đã cho.

Làm thế nào nó hoạt động

  1. Ghi nhớ tất cả các thay đổi đối với các phần tử đầu vào bởi người dùng (lắng nghe các sự kiện thay đổi) và cả JavaScript (bằng cách chặn $ el.val () cho các phần tử jQuery / jQLite). Giá trị đã thay đổi đó được lưu trữ trên phần tử trong thuộc tính riêng.

  2. Kiểm tra một phần tử để tự động điền: So sánh giá trị hiện tại của phần tử với giá trị đã nhớ. Nếu nó khác, hãy kích hoạt một sự kiện thay đổi.

Sự phụ thuộc

AngularJS hoặc jQuery (hoạt động với một hoặc cả hai)

Thêm thông tin và nguồn trên trang github .

Bạn có thể đọc bản gốc Angular Issue # 1460 trên Github tại đây.


2
Điều này không làm việc cho các trường hợp của tôi. checkAndTriggerAutoFillEvent () được kích hoạt và tạo ra các sự kiện, nhưng AngularJS không bao giờ cập nhật các mô hình của nó và cho rằng các trường trống.
Splaktar

Tôi không gặp bất kỳ vấn đề gì khi sử dụng polyill này. Nếu bạn không thể làm cho nó hoạt động bình thường, bạn nên tạo một câu hỏi riêng bao gồm một số mã. Nếu tìm thấy lỗi, bạn nên kiểm tra vé trên github hoặc mở một vé mới.
orszaczky

Yep, tôi nghĩ rằng nó có liên quan đến lỗi này: github.com/tbosch/autofill-event/issues/11
Splaktar

1
ngModelOptionskết hợp với autofill-eventnghĩa là giờ đây bạn có thể chỉ định changelà một trong các updateOnsự kiện để đảm bảo mô hình của bạn được đồng bộ hóa chính xác.
morloch

10

Mã bẩn, hãy kiểm tra xem sự cố https://github.com/angular/angular.js/issues/1460#issuecomment-18572604 đã được khắc phục chưa trước khi sử dụng mã này. Chỉ thị này kích hoạt các sự kiện khi trường được điền, không chỉ trước khi gửi (nó cần thiết nếu bạn phải xử lý đầu vào trước khi gửi)

 .directive('autoFillableField', function() {
    return {
                   restrict: "A",
                   require: "?ngModel",
                   link: function(scope, element, attrs, ngModel) {
                       setInterval(function() {
                           var prev_val = '';
                           if (!angular.isUndefined(attrs.xAutoFillPrevVal)) {
                               prev_val = attrs.xAutoFillPrevVal;
                           }
                           if (element.val()!=prev_val) {
                               if (!angular.isUndefined(ngModel)) {
                                   if (!(element.val()=='' && ngModel.$pristine)) {
                                       attrs.xAutoFillPrevVal = element.val();
                                       scope.$apply(function() {
                                           ngModel.$setViewValue(element.val());
                                       });
                                   }
                               }
                               else {
                                   element.trigger('input');
                                   element.trigger('change');
                                   element.trigger('keyup');
                                   attrs.xAutoFillPrevVal = element.val();
                               }
                           }
                       }, 300);
                   }
               };
});

5

Có vẻ như giải pháp rõ ràng về phía trước. Không cần jQuery.

CẬP NHẬT:

  • Mô hình chỉ được cập nhật khi giá trị mô hình không bằng giá trị đầu vào thực tế.
  • Việc kiểm tra không dừng lại ở lần tự động điền đầu tiên. Trong trường hợp nếu bạn muốn sử dụng một tài khoản khác chẳng hạn.

app.directive('autofillable', ['$timeout', function ($timeout) {
    return {
        scope: true,
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl) {
            scope.check = function(){
                var val = elem[0].value;
                if(ctrl.$viewValue !== val){
                    ctrl.$setViewValue(val)
                }
                $timeout(scope.check, 300);
            };
            scope.check();
        }
    }
}]);

4
+1 giải pháp tốt, tương tự như những gì tôi đã nghĩ ra. Cách bổ sung duy nhất tôi muốn đề xuất là trước tiên hãy kiểm tra xem mô hình có phải là $pristinetrước khi thay đổi nó hay không và sau khi thay đổi nó giữ $pristinetrạng thái của nó . Nếu không, bạn sẽ thấy rằng nếu một biểu mẫu được tải mà không có dữ liệu tự động điền, thì chỉ thị trên sẽ vẫn cập nhật mô hình và sau đó làm cho nó dirtymặc dù điều khiển biểu mẫu vẫn được coi là không bị ảnh hưởng. ví dụ ở đây, sử dụng chỉ thị của bạn. Tôi đã nhận xét về mã mà tôi sẽ thêm vào đó: jsfiddle.net/OACDesigns/L8Sja/4
OACDesigns

1
ngoài ra, tôi nghĩ là scope:truenênscope:{}
OACDesigns

4

Giải pháp 1 [Sử dụng $ timeout]:

Chỉ thị:

app.directive('autoFillSync', function($timeout) {
    return {
      require: 'ngModel',
      link: function(scope, elem, attrs, model) {
          var origVal = elem.val();
          $timeout(function () {
              var newVal = elem.val();
              if(model.$pristine && origVal !== newVal) {
                  model.$setViewValue(newVal);
              }
          }, 500);
      }
    };
});

HTML:

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

Giải pháp 2 [Sử dụng các sự kiện góc]:

Tham khảo: Câu trả lời của Becko

Chỉ thị:

app.directive("autofill", function () {
    return {
        require: "ngModel",
        link: function (scope, element, attrs, ngModel) {
            scope.$on("autofill:update", function() {
                ngModel.$setViewValue(element.val());
            });
        }
    };
});

HTML:

<form name="myForm" ng-submit="login()">
  <label for="username">Username</label>
  <input type="text" id="username" name="username" ng-model="username" autofill/><br/>
  <label for="password">Password</label>
  <input type="password" id="password" name="password" ng-model="password" autofill/><br/>
  <button type="submit">Login</button>
</form>

Giải pháp 3 [Sử dụng lệnh gọi phương thức chuyển tiếp]:

Chỉ thị:

app.directive('autoFill', function() {
    return {
        restrict: 'A',
        link: function(scope,element) {
            scope.submit = function(){
                scope.username = element.find("#username").val();
                scope.password = element.find("#password").val();
                scope.login();//call a login method in your controller or write the code here itself
            }

        }
    };
});

HTML:

<form name="myForm" auto-fill ng-submit="submit()">
   <label for="username">Username</label>
   <input type="text" id="username" name="username" ng-model="username" />
   <label for="password">Password</label>
   <input type="password" id="password" name="password" ng-model="password" />
   <button type="submit">Login</button>
</form>

2
Giải pháp 1 hoạt động rất tốt trong một thời gian, nhưng bây giờ trên anglejs 1.4.9, nó không hoạt động nữa. Kiểm tra model.$validtrong lợi nhuận chỉ đúng cả trước và sau $setViewValue, nhưng yếu tố này vẫn là với ng-invalidlớp
John

4

Chà, cách dễ nhất là mô phỏng hành vi của trình duyệt, vì vậy nếu có vấn đề với sự kiện thay đổi, chỉ cần tự khắc phục sự cố. Đơn giản hơn nhiều.

Chỉ thị:

yourModule.directive('triggerChange', function($sniffer) {
    return {
        link : function(scope, elem, attrs) {
            elem.on('click', function(){
                $(attrs.triggerChange).trigger(
                    $sniffer.hasEvent('input') ? 'input' : 'change'
                );
            });
        },
        priority : 1
    }
});

HTML:

<form >
    <input data-ng-model="user.nome" type="text" id="username">

    <input data-ng-model="user.senha" type="password" id="password" >

    <input type="submit" data-ng-click="login.connect()" id="btnlogin" 
           data-trigger-change="#password,#username"/>
</form>

Bạn có thể thực hiện một số biến thể, chẳng hạn như đặt chỉ thị trên biểu mẫu và kích hoạt sự kiện trên tất cả các đầu vào với lớp .dirty khi gửi biểu mẫu.


3

Đây là cách jQuery:

$(window).load(function() {
   // updates autofilled fields
   window.setTimeout(function() {
     $('input[ng-model]').trigger('input');
   }, 100);
 });

Đây là cách Angular:

 app.directive('autofill', ['$timeout', function ($timeout) {
    return {
        scope: true,
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl) {
            $timeout(function(){
                $(elem[0]).trigger('input');
                // elem.trigger('input'); try this if above don't work
            }, 200)
        }
    }
}]);

HTML

<input type="number" autofill /> 

2
Cách hoàn toàn không góc cạnh.
gorpacrate

1
@gorpacrate: Bây giờ hãy kiểm tra nó theo cách góc cạnh.
Nishchit Dhanani

2
Các tab của Angular Way có quá nhiều khoảng trắng. Chỉ giỡn thôi. Tôi thích cuộn ngang.
Daniel Birowsky Popeski

điều này không hoạt động trong góc vì không có chức năng kích hoạt trên phần tử. Tôi nghĩ rằng điều này sẽ yêu cầu bao gồm jquery
Tomas

1
triggerHandler('input')nên ok nếu bạn không có đầy đủ thổi jquery
Mutmatt

1

Đây là một giải pháp khác ít hack hơn, nhưng yêu cầu một số mã bổ sung trong bộ điều khiển.

HTML:

<form ng-submit="submitForm()" ng-controller="FormController">
    <input type="text" ng-model="username" autocomplete-username>
    <input type="submit">
</form>

Chỉ thị (CoffeeScript):

directives.directive 'autocompleteUsername', ->
    return (scope, element) ->
        scope.getUsername = ->
            element.val()

Bộ điều khiển:

controllers.controller 'FormController', [->
    $scope.submitForm = ->
        username = $scope.getUsername?() ? $scope.username
        # HTTP stuff...
]

Bạn có cái này trong JavaScript vani?
f1lt3r

CoffeeScript.org cung cấp một trình dịch: thực hiện tại đây
jab

1

Đây là giải pháp duy nhất mà tôi đã tìm thấy cho phép tất cả các xác thực Angular 'của tôi hoạt động như được thiết kế bao gồm vô hiệu hóa / kích hoạt nút gửi. Cài đặt với bower và 1 thẻ script. Bazinga!

https://github.com/tbosch/autofill-event


1
điền nhiều này không phù hợp với nút gửi / đầu vào liên kết với trạng thái biểu mẫu. trừ khi bạn nhấp vào trang bất kỳ điểm nào bạn muốn kích hoạt thông báo (có vẻ như hành động kích hoạt trình duyệt thực hiện một số thao tác điền thực sự), khi đó nút sẽ bật. Trang kiểm tra với các bài kiểm tra thủ công
e-cloud

1

Tôi thay đổi giá trị mô hình, thay vì sử dụng một hàm thời gian chờ.

Đây là mã của tôi:

module.directive('autoFill', [ function() {
    return {
        require: 'ngModel',
        link:function(scope, element, attr, ngModel) {
            var origVal = element.val();
            if(origVal){
                ngModel.$modelValue = ngModel.$modelValue || origVal;
            }
        }
    };
}]);

1

Cách giải quyết một lớp trong trình xử lý gửi (yêu cầu jQuery):

if (!$scope.model) $scope.model = $('#input_field').val();

Nó không thực sự là một lớp lót nếu nó nằm trong một chỉ thị, mà nó chắc chắn phải như vậy.
isherwood

0

Tôi buộc gửi một $ setValue (val ()): (điều này hoạt động mà không cần jQuery)

   var ValidSubmit = ['$parse', function ($parse) {
    return {
        compile: function compile(tElement, tAttrs, transclude) {
            return {
                post: function postLink(scope, element, iAttrs, controller) {
                    var form = element.controller('form');
                    form.$submitted = false;
                    var fn = $parse(iAttrs.validSubmit);
                    element.on('submit', function(event) {
                        scope.$apply(function() {
                            var inputs = element.find('input');
                            for(var i=0; i < inputs.length; i++) {
                                var ele = inputs.eq(i);
                                var field = form[inputs[i].name];
                                field.$setViewValue(ele.val());
                            }
                            element.addClass('ng-submitted');
                            form.$submitted = true;
                            if(form.$valid) {
                                fn(scope, {$event:event});
                            }
                        });
                    });
                    scope.$watch(function() { return form.$valid}, function(isValid) {
                        if(form.$submitted == false) return;
                        if(isValid) {
                            element.removeClass('has-error').addClass('has-success');
                        } else {
                            element.removeClass('has-success');
                            element.addClass('has-error');
                        }
                    });
                }
            }
        }
    }
}]
app.directive('validSubmit', ValidSubmit);

0

Tôi rất mới với Angularjs, nhưng tôi đã tìm thấy một giải pháp đơn giản cho vấn đề đó => Buộc Angular đánh giá lại biểu thức ... bằng cách thay đổi nó! (tất nhiên bạn cần nhớ giá trị ban đầu để hoàn nguyên về trạng thái ban đầu) Đây là cách nó hoạt động trong hàm bộ điều khiển của bạn để gửi biểu mẫu:

    $scope.submit = function () {
                var oldpassword = $scope.password;
                $scope.password = '';
                $scope.password = oldpassword;
//rest of your code of the submit function goes here...

tất nhiên, giá trị được nhập trong phần nhập mật khẩu của bạn đã được đặt bởi các cửa sổ chứ không phải bởi người dùng.


0

Bạn có thể thử mã này:

yourapp.directive('autofill',function () {

    return {
        scope: true,
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl) {
            var origVal = elem.val();
            if (origVal != '') {
                elem.trigger('input');
            }
        }
    }
});

0

Một sửa đổi nhỏ cho câu trả lời này ( https://stackoverflow.com/a/14966711/3443828 ): sử dụng khoảng thời gian $ thay vì $ timeout để bạn không phải chạy trình duyệt.

mod.directive('autoFillSync', function($interval) {
    function link(scope, element, attrs, ngModel) {
        var origVal = element.val();
        var refresh = $interval(function() {
          if (!ngModel.$pristine) {
            $interval.cancel(refresh);
          }else{
            var newVal = element.val();
            if (origVal !== newVal) {
              ngModel.$setViewValue(newVal);
              $interval.cancel(refresh);
            }
          }
        }, 100);
    }

    return {
      require: 'ngModel',
      link: link
    }
  });

0

Đây là giải pháp tôi đã sử dụng trong các biểu mẫu của mình.

.directive('autofillSync', [ function(){
  var link = function(scope, element, attrs, ngFormCtrl){
    element.on('submit', function(event){
      if(ngFormCtrl.$dirty){
        console.log('returning as form is dirty');
        return;
      }   
      element.find('input').each(function(index, input){
        angular.element(input).trigger('input');
      }); 
    }); 
  };  
  return {
    /* negative priority to make this post link function run first */
    priority:-1,
    link: link,
    require: 'form'
  };  
}]);

Và mẫu của biểu mẫu sẽ là

<form autofill-sync name="user.loginForm" class="login-form" novalidate ng-submit="signIn()">
    <!-- Input fields here -->
</form>

Bằng cách này, tôi có thể chạy bất kỳ trình phân tích cú pháp / định dạng nào mà tôi có trên ng-model của mình và có chức năng gửi trong suốt.


0

Giải pháp không có chỉ thị:

.run(["$window", "$rootElement", "$timeout", function($window, $rootElement, $timeout){

        var event =$window.document.createEvent("HTMLEvents");
        event.initEvent("change", true, true);

        $timeout(function(){

            Array.apply(null, $rootElement.find("input")).forEach(function(item){
                if (item.value.length) {
                    item.$$currentValue = item.value;
                    item.dispatchEvent(event);
                }
            });

        }, 500);
    }])

0

Đây là một bản sửa lỗi đơn giản phù hợp với tất cả các trường hợp tôi đã thử nghiệm trên cả Firefox và Chrome. Lưu ý rằng với câu trả lời hàng đầu (chỉ thị w / timeout), tôi đã gặp vấn đề với -

  • Nút quay lại / chuyển tiếp của trình duyệt, không kích hoạt lại các sự kiện tải trang (vì vậy bản sửa lỗi không áp dụng)
  • Đang tải thông tin đăng nhập một thời gian sau khi tải trang. Ví dụ: trong Firefox, nhấp đúp vào hộp đăng nhập và chọn từ thông tin đăng nhập đã lưu trữ.
  • Cần một giải pháp cập nhật trước khi gửi biểu mẫu vì tôi tắt nút Đăng nhập cho đến khi cung cấp đầu vào hợp lệ

Bản sửa lỗi này rõ ràng là rất ngu ngốc và khó hiểu, nhưng nó hoạt động 100% thời gian -

function myScope($scope, $timeout) {
    // ...
    (function autoFillFix() {
        $timeout(function() { 
            $('#username').trigger('change'); 
            $('#password').trigger('change'); 
            autoFillFix(); }, 500);                    
    })();
}

1
có thể thay thế $timeoutvới $intervalđể cung cấp cho tương lai devs một bối cảnh chút hơn và thoát khỏi các cuộc gọi đệ quy tìm kiếm kỳ lạ xảy ra ở đó
Mutmatt

0

Không có giải pháp nào trong số này phù hợp với trường hợp sử dụng của tôi. Tôi có một số trường biểu mẫu sử dụng ng-change để theo dõi sự thay đổi. Việc sử dụng $watchkhông có ích gì vì nó không được kích hoạt bởi tính năng tự động điền. Vì tôi không có nút gửi nên không có cách nào dễ dàng để chạy một số giải pháp và tôi đã không thành công khi sử dụng các khoảng thời gian.

Tôi đã tắt tính năng tự động điền - không lý tưởng nhưng ít gây nhầm lẫn hơn cho người dùng.

<input readonly onfocus="this.removeAttribute('readonly');">

Tìm thấy câu trả lời ở đây


-1

Nếu bạn đang sử dụng jQuery, bạn có thể thực hiện việc này khi gửi biểu mẫu:

HTML:

<form ng-submit="submit()">
    <input id="email" ng-model="password" required 
           type="text" placeholder="Your email">
    <input id="password" ng-model="password" required 
           type="password" placeholder="Password">
</form>

JS:

 $scope.submit = function() {
     $scope.password = $('#password').val();
}

1
Mặc dù điều này có thể hoạt động nhưng không hợp lý đối với các dạng phức tạp hơn.
origin1tech

-1

Nếu bạn muốn đơn giản, chỉ cần lấy giá trị bằng javascript

Trong bộ điều khiển js góc cạnh của bạn:

var username = document.getElementById ('tên người dùng'). value;


Tôi nghĩ bạn không hiểu vấn đề là gì
aelor
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.