วิธีแก้ปัญหาการป้อนอัตโนมัติของเบราว์เซอร์ AngularJS โดยใช้คำสั่ง


111

เมื่อส่งแบบฟอร์มใน 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()ค่าที่ส่งคืน ฉันจะทำมันให้สำเร็จได้อย่างไร?


รหัสนี้ดูดีในตอนแรกอาย ... แต่ส่วนที่เหลืออยู่ที่ไหน (มาร์กอัป ฯลฯ )? คุณมีซอหรือท่อนที่เราเห็นไหม?
Ben Lesh

นี่คือplunk : plnkr.co/edit/CHrBAVU9Ycl2ex2DRr6Rฉันไม่แน่ใจว่ามันใช้งานได้โดยตรงกับ plunker หรือไม่เพราะมันทำงานใน iframe
lucassp

1
คุณไม่จำเป็นต้องกำหนดขอบเขต $ ใช้ภายใน $ timeout ของ angular คุณอาจต้องใช้ภายใน window.setTimeout ดั้งเดิม แต่ควรใช้เชิงมุมมากกว่า
gorpacrate

1
มีการแก้ไข polyfill "อย่างเป็นทางการ"จาก Angular dev tboschสำหรับปัญหานี้ โปรดดูรายละเอียดในคำตอบstackoverflow.com/a/25687396/3009639ด้านล่าง
orszaczky

น่าเสียดายที่การแก้ไข "อย่างเป็นทางการ" คือการละทิ้งและใช้งานไม่ได้ในเบราว์เซอร์จำนวนมาก มีการยื่นปัญหา แต่ไม่ได้รับการแก้ไขดังนั้นการค้นหาจึงดำเนินต่อไป ...
cyberwombat

คำตอบ:


45

เห็นได้ชัดว่านี่เป็นปัญหาที่ทราบแล้วของ Angular และกำลังเปิดอยู่

ฉันไม่แน่ใจว่าคุณสามารถทำอะไรที่นี่ได้นอกเหนือจากการทำงานบางอย่างที่คุณกำลังพยายาม ดูเหมือนว่าคุณมาถูกทางแล้ว ฉันไม่สามารถใช้เบราว์เซอร์เพื่อพยายามจำรหัสผ่านสำหรับกลุ่มของคุณได้ดังนั้นฉันไม่แน่ใจว่าจะได้ผลหรือไม่ แต่ลองดู:

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>

ฉันคิดว่าคุณต้องทำให้แนวทางของคุณง่ายขึ้นเล็กน้อย สิ่งหนึ่งที่ฉันแนะนำอย่างแน่นอนคือตรวจสอบngModel.$pristineและให้แน่ใจว่าคุณไม่ได้เขียนทับข้อมูลที่ผู้ใช้ไม่ดี นอกจากนี้ 3 วินาทีอาจนานเกินไป คุณไม่ควรเรียก $ apply () ใน $ timeout, BTW มันควรจัดคิว $ Digest ให้คุณโดยอัตโนมัติ

การจับที่แท้จริง: เบราว์เซอร์ของคุณจะเอาชนะ Angular ไปสู่การดำเนินการหรือไม่? แล้วเบราว์เซอร์ของฉันล่ะ?

นี่อาจเป็นสงครามที่ไม่สามารถเอาชนะได้ซึ่งเป็นสาเหตุที่ Angular (หรือ Knockout) ไม่สามารถแก้ไขได้ในทันที ไม่มีการรับประกันสถานะของข้อมูลในข้อมูลที่คุณป้อนในขณะที่คำสั่งเริ่มต้นดำเนินการ ยังไม่ถึงเวลาเริ่มต้นของ Angular .... ดังนั้นจึงเป็นปัญหาที่ยุ่งยากในการแก้ไข


1
จุดดีเกี่ยวกับ $ บริสุทธิ์ 3 วินาทีมีไว้เพื่อการทดสอบเท่านั้น ดูเหมือนว่ากล่องโต้ตอบ "บันทึกรหัสผ่าน" จะทำงานบน Safari นั่นเป็นอีกปัญหาหนึ่งที่ฉันต้องตรวจสอบ
lucassp

แค่หลอกเขาด้วยการจัดเก็บในท้องถิ่น :) ... ฉันจะคิดเกี่ยวกับมัน แต่ฉันมีข้อสงสัยเกี่ยวกับความเป็นไปได้ในการทำให้การป้อนอัตโนมัติทำงานร่วมกับการผูกแบบสองทาง
Ben Lesh

ใช่ แต่ฉันยังคงต้องสามารถอัปเดตโมเดลจากคำสั่งเพื่อให้ใช้งานได้
lucassp

1
ฉันล้อเล่นเกี่ยวกับ localStorage คุณไม่ต้องการเก็บรหัสผ่านไว้ที่นั่น
Ben Lesh

1
สิ่งนี้ใช้ไม่ได้กับ Safari และการป้อนอัตโนมัติด้วยบัตรเครดิตเนื่องจากการป้อนอัตโนมัตินี้ถูกเรียกใช้เมื่อใดก็ได้โดยผู้ใช้
Dallas Clark

35

นี่คือโซลูชันที่แฮ็กน้อยกว่าโซลูชันอื่น ๆ ที่นำเสนอและเป็น 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>

2
อันนี้ใช้ได้ เราพยายามส่วนใหญ่ข้างต้นโดยไม่มีผลลัพธ์ใด ๆ ขอบคุณ !!! ผลลัพธ์คือmobbr.com
Patrick Savalle

1
เนื่องจากใช้ jQuery จึงไม่คาดว่าจะทำงานได้หากไม่มี jQuery
Quinn Strahl

1
เราอยู่ที่นี่ในปี 2018 และนี่ยังคงเป็นการแก้ไข ขอบคุณเอเสเคียล!
Scott Manny

35

คุณไม่จำเป็นต้องใช้ a $timeoutหรืออะไรเช่นนี้ คุณสามารถใช้ระบบเหตุการณ์

ฉันคิดว่ามันเป็น Angularish มากกว่าและไม่ได้ขึ้นอยู่กับ jQuery หรือการจับเหตุการณ์ที่กำหนดเอง

ตัวอย่างเช่นในตัวจัดการการส่งของคุณ:

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

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

จากนั้นคุณสามารถมีautofillคำสั่งเช่นนี้:

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

สุดท้าย HTML ของคุณจะเป็นดังนี้:

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

14
ในกรณีของฉันปุ่มส่งถูกปิดใช้งานในขณะที่อินพุตว่างเปล่า
gorpacrate

4
คุณไม่เคยมีปัญหากับสิ่งนี้เพราะ async หรือไม่? ที่การเรียกเข้าสู่ระบบไปยังเซิร์ฟเวอร์ออกไปแล้วก่อนที่เหตุการณ์จะถูกจำลองแบบและคำสั่งมีเวลาในการอัปเดตขอบเขตหรือไม่
Sander

12

ไม่ต้องแฮ็คอีกต่อไป! Angular dev tboschสร้าง polyfill ที่ทริกเกอร์เหตุการณ์การเปลี่ยนแปลงเมื่อเบราว์เซอร์เปลี่ยนฟิลด์แบบฟอร์มโดยไม่เรียกใช้เหตุการณ์การเปลี่ยนแปลง:

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

ในตอนนี้พวกเขาจะไม่สร้างสิ่งนี้ลงในโค้ด Angular เนื่องจากนี่เป็นการแก้ไขข้อบกพร่องของเบราว์เซอร์และยังทำงานได้โดยไม่ต้องใช้ Angular (เช่นแอป jQuery ธรรมดา)

"โพลีฟิลล์จะตรวจสอบการเปลี่ยนแปลงในการโหลดเอกสารและเมื่ออินพุตเหลืออยู่ (เฉพาะในรูปแบบเดียวกัน) อย่างไรก็ตามคุณสามารถเรียกใช้การตรวจสอบด้วยตนเองได้หากต้องการ

โครงการมีการทดสอบหน่วยเช่นเดียวกับการทดสอบกึ่งอัตโนมัติดังนั้นในที่สุดเราก็มีสถานที่สำหรับรวบรวมกรณีการใช้งานที่แตกต่างกันทั้งหมดพร้อมกับการตั้งค่าเบราว์เซอร์ที่จำเป็น

โปรดทราบ: polyfill นี้ใช้ได้กับแอพ AngularJS ธรรมดากับแอพ AngularJS / jQuery แต่ยังใช้กับแอพ jQuery ธรรมดาที่ไม่ใช้ Angular ด้วย "

สามารถติดตั้งกับ:

bower install autofill-event --save

เพิ่มสคริปต์autofill-event.js หลัง jQuery หรือ Angular ในเพจของคุณ

สิ่งนี้จะทำสิ่งต่อไปนี้:

  • หลังจาก DOMContentLoaded: ตรวจสอบช่องป้อนข้อมูลทั้งหมด
  • ช่องที่เหลืออยู่: ตรวจสอบช่องอื่น ๆ ทั้งหมดในรูปแบบเดียวกัน

API (เพื่อเรียกใช้การตรวจสอบด้วยตนเอง):

  • $el.checkAndTriggerAutoFillEvent(): ดำเนินการตรวจสอบองค์ประกอบ DOM ทั้งหมดในองค์ประกอบ jQuery / jQLite ที่กำหนด

มันทำงานอย่างไร

  1. จดจำการเปลี่ยนแปลงทั้งหมดขององค์ประกอบอินพุตโดยผู้ใช้ (การรับฟังเหตุการณ์การเปลี่ยนแปลง) และโดย JavaScript (โดยการสกัดกั้น $ el.val () สำหรับองค์ประกอบ jQuery / jQLite) ค่าที่เปลี่ยนแปลงนั้นจะถูกเก็บไว้ในองค์ประกอบในคุณสมบัติส่วนตัว

  2. การตรวจสอบองค์ประกอบสำหรับการเติมอัตโนมัติ: เปรียบเทียบค่าปัจจุบันขององค์ประกอบกับค่าที่จำได้ หากแตกต่างกันให้ทริกเกอร์เหตุการณ์การเปลี่ยนแปลง

การพึ่งพา

AngularJS หรือ jQuery (ใช้ได้กับอย่างใดอย่างหนึ่งหรือทั้งสองอย่าง)

ข้อมูลเพิ่มเติมและแหล่งที่มาในหน้า GitHub

Original Angular Issue # 1460 บน Github สามารถอ่านได้ที่นี่


2
สิ่งนี้ใช้ไม่ได้กับกรณีของฉัน checkAndTriggerAutoFillEvent () ถูกทริกเกอร์และสร้างเหตุการณ์ แต่ AngularJS ไม่เคยอัปเดตโมเดลและคิดว่าฟิลด์ว่างเปล่า
Splaktar

ฉันไม่มีปัญหาในการใช้โพลีอิลนี้ หากคุณไม่สามารถทำให้มันทำงานได้อย่างถูกต้องคุณควรสร้างคำถามแยกต่างหากรวมถึงรหัสบางส่วน หากคุณพบข้อบกพร่องคุณควรตรวจสอบตั๋วใน github หรือเปิดใหม่
orszaczky

ใช่ฉันคิดว่ามันเกี่ยวข้องกับข้อผิดพลาดนี้: github.com/tbosch/autofill-event/issues/11
Splaktar

1
ngModelOptionsรวมกับautofill-eventวิธีการในขณะนี้คุณสามารถระบุchangeเป็นหนึ่งในupdateOnเหตุการณ์เพื่อให้แน่ใจว่าโมเดลของคุณซิงค์ถูกต้อง
morloch

10

รหัสสกปรกตรวจสอบว่าปัญหาhttps://github.com/angular/angular.js/issues/1460#issuecomment-18572604ได้รับการแก้ไขก่อนใช้รหัสนี้หรือไม่ คำสั่งนี้จะทริกเกอร์เหตุการณ์เมื่อกรอกข้อมูลในฟิลด์ไม่ใช่เฉพาะก่อนส่ง (จำเป็นหากคุณต้องจัดการอินพุตก่อนส่ง)

 .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

ดูเหมือนวิธีแก้ปัญหาที่ชัดเจนตรงไปตรงมา ไม่จำเป็นต้องใช้ jQuery

อัพเดท:

  • โมเดลจะอัปเดตก็ต่อเมื่อค่าโมเดลไม่เท่ากับค่าอินพุตจริง
  • การตรวจสอบไม่ได้หยุดลงในการป้อนอัตโนมัติครั้งแรก ในกรณีที่คุณต้องการใช้บัญชีอื่นเช่น

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 ทางออกที่ดีคล้ายกับสิ่งที่ฉันคิดขึ้นมา สิ่งเดียวที่ฉันขอแนะนำคือให้ตรวจสอบก่อนว่าเป็นรุ่น$pristineก่อนที่จะเปลี่ยนหรือไม่จากนั้นหลังจากเปลี่ยนแล้วให้เป็น$pristineสถานะ มิฉะนั้นคุณจะพบว่าหากฟอร์มถูกโหลดโดยไม่มีข้อมูลป้อนอัตโนมัติคำสั่งข้างต้นจะยังคงอัปเดตโมเดลและทำให้เป็นแบบนั้นในภายหลังdirtyแม้ว่าการควบคุมฟอร์มจะยังคงถือว่าไม่ถูกแตะต้อง ตัวอย่างที่นี่โดยใช้คำสั่งของคุณ ฉันได้แสดงความคิดเห็นเกี่ยวกับรหัสที่ฉันจะเพิ่มเข้าไป: jsfiddle.net/OACDesigns/L8Sja/4
OACDesigns

1
ฉันคิดว่าscope:trueควรจะเป็นscope:{}
OACDesigns

4

โซลูชันที่ 1 [โดยใช้ $ timeout]:

คำสั่ง:

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>

แนวทางที่ 2 [การใช้เหตุการณ์เชิงมุม]:

Ref: คำตอบของ Becko

คำสั่ง:

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>

โซลูชันที่ 3 [โดยใช้การเรียกวิธีการถ่ายทอด]:

คำสั่ง:

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
โซลูชันที่ 1 ทำงานได้ดีในช่วงเวลาหนึ่ง แต่ตอนนี้ใน angularjs 1.4.9 ไม่ทำงานอีกต่อไป การตรวจสอบmodel.$validคำสั่งส่งคืนจริงทั้งก่อนและหลัง$setViewValueแต่องค์ประกอบยังคงอยู่ในng-invalidคลาส
จอห์น

4

วิธีที่ง่ายที่สุดคือเลียนแบบพฤติกรรมของเบราว์เซอร์ดังนั้นหากมีปัญหากับเหตุการณ์การเปลี่ยนแปลงให้เริ่มการทำงานด้วยตัวเอง ง่ายกว่ามาก

คำสั่ง:

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>

คุณสามารถเปลี่ยนรูปแบบบางอย่างได้เช่นใส่คำสั่งลงในแบบฟอร์มและเริ่มต้นเหตุการณ์ในอินพุตทั้งหมดด้วยคลาส. Dirty ในการส่งแบบฟอร์ม


3

นี่คือวิธี jQuery:

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

นี่คือวิธีเชิงมุม:

 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
วิธีที่ไม่ใช่เชิงมุมโดยสิ้นเชิง
gorpacrate

1
@gorpacrate: ลองดูด้วยวิธีเชิงมุม
Nishchit Dhanani

2
แท็บของ Angular Way มีช่องว่างมากเกินไป เพียงแค่ kiddin ฉันชอบการเลื่อนแนวนอน
Daniel Birowsky Popeski

สิ่งนี้ไม่ทำงานในเชิงมุมเนื่องจากไม่มีฟังก์ชันทริกเกอร์ในองค์ประกอบ ฉันคิดว่าสิ่งนี้จะต้องรวม jquery
Tomas

1
triggerHandler('input')น่าจะโอเคถ้าคุณไม่มี jquery เต็มรูปแบบ
Mutmatt

1

นี่เป็นวิธีแก้ปัญหาอื่นที่แฮ็กน้อย แต่ต้องใช้รหัสพิเศษในคอนโทรลเลอร์

HTML:

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

คำสั่ง (CoffeeScript):

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

ตัวควบคุม:

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

คุณมีสิ่งนี้ในวานิลลา JavaScript หรือไม่?
f1lt3r

CoffeeScript.org มีผู้แปล: เสร็จแล้วที่นี่
กระทุ้ง

1

นี่เป็นทางออกเดียวที่ฉันพบว่าอนุญาตให้การตรวจสอบความถูกต้องของ Angular ทั้งหมดของฉันทำงานได้ตามที่ออกแบบไว้รวมถึงปุ่มปิด / เปิดใช้งานปุ่มส่ง ติดตั้งด้วย bower และ 1 script tag บาซิงกา!

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


1
การเติมโพลีนี้ไม่พอดีกับปุ่มส่ง / อินพุตที่เชื่อมโยงกับสถานะแบบฟอร์ม เว้นแต่คุณจะคลิกที่หน้าจุดใดก็ได้ที่คุณต้องการเรียกใช้การสรุป (ดูเหมือนว่าการกระทำจะกระตุ้นให้เบราว์เซอร์ทำการเติมจริง) จากนั้นปุ่มจะเปิดใช้งาน หน้าทดสอบพร้อมการทดสอบด้วยตนเอง
e-cloud

1

การเปลี่ยนค่าโมเดลแทนที่จะใช้ฟังก์ชันการหมดเวลาได้ผลสำหรับฉัน

นี่คือรหัสของฉัน:

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

วิธีแก้ปัญหาแบบซับเดียวในตัวจัดการการส่ง (ต้องใช้ jQuery):

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

มันไม่ใช่ซับเดียวจริงๆถ้ามันอยู่ในคำสั่งซึ่งมันควรจะเป็นอย่างแน่นอน
isherwood

0

ฉันบังคับ $ setValue (val ()) เมื่อส่ง: (ใช้งานได้โดยไม่มี 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

ฉันยังใหม่กับ Angularjs มาก แต่ฉันพบวิธีง่ายๆสำหรับปัญหานั้น => บังคับให้ Angular ประเมินนิพจน์อีกครั้ง ... โดยการเปลี่ยน! (แน่นอนว่าคุณต้องจำค่าเริ่มต้นเพื่อเปลี่ยนกลับเป็นสถานะเริ่มต้น) นี่คือวิธีที่ใช้ในฟังก์ชันคอนโทรลเลอร์ของคุณในการส่งแบบฟอร์ม:

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

โดยที่แน่นอนค่าที่ป้อนในการป้อนรหัสผ่านของคุณถูกกำหนดโดย windows ไม่ใช่โดยผู้ใช้


0

คุณสามารถลองใช้รหัสนี้:

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

การแก้ไขเล็กน้อยสำหรับคำตอบนี้ ( https://stackoverflow.com/a/14966711/3443828 ): ใช้ $ interval แทน $ timeout เพื่อให้คุณไม่ต้องแข่งเบราว์เซอร์

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

นี่คือวิธีแก้ปัญหาที่ฉันใช้ในแบบฟอร์มของฉัน

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

และเทมเพลตของฟอร์มจะเป็น

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

ด้วยวิธีนี้ฉันสามารถเรียกใช้ตัวแยกวิเคราะห์ / ฟอร์แมตใด ๆ ที่ฉันมีใน ng-model ของฉันและมีฟังก์ชันการส่งที่โปร่งใส


0

โซลูชันที่ไม่มีคำสั่ง:

.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

นี่เป็นการแก้ไขง่ายๆที่ใช้ได้กับทุกกรณีที่ฉันเคยทดสอบทั้งใน Firefox และ Chrome โปรดทราบว่าด้วยคำตอบด้านบน (คำสั่ง w / หมดเวลา) ฉันมีปัญหากับ -

  • ปุ่มย้อนกลับ / ไปข้างหน้าของเบราว์เซอร์อย่าเริ่มเหตุการณ์การโหลดหน้าซ้ำ (ดังนั้นการแก้ไขจึงใช้ไม่ได้)
  • การโหลดข้อมูลรับรองบางครั้งหลังจากโหลดหน้า เช่นใน Firefox ดับเบิลคลิกที่ช่องล็อกอินและเลือกจากข้อมูลประจำตัวที่เก็บไว้
  • ต้องการโซลูชันที่อัปเดตก่อนการส่งแบบฟอร์มเนื่องจากฉันปิดใช้งานปุ่มเข้าสู่ระบบจนกว่าจะมีการป้อนข้อมูลที่ถูกต้อง

เห็นได้ชัดว่าการแก้ไขนี้ดูโง่และแฮ็คมาก แต่มันใช้งานได้ 100% ตลอดเวลา -

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

1
สามารถแทนที่$timeoutด้วย$intervalเพื่อให้นักพัฒนาซอฟต์แวร์ในอนาคตมีบริบทมากขึ้นเล็กน้อยและกำจัดการโทรซ้ำที่ดูแปลก ๆ ที่เกิดขึ้นที่นั่น
Mutmatt

0

ไม่มีวิธีแก้ปัญหาเหล่านี้สำหรับกรณีการใช้งานของฉัน ฉันมีช่องแบบฟอร์มที่ใช้ ng-change เพื่อเฝ้าดูการเปลี่ยนแปลง การใช้งาน$watchไม่ใช่ความช่วยเหลือเนื่องจากไม่ได้ถูกกระตุ้นโดยการป้อนอัตโนมัติ เนื่องจากฉันไม่มีปุ่มส่งจึงไม่มีวิธีง่ายๆในการเรียกใช้โซลูชันบางอย่างและฉันใช้ช่วงเวลาไม่สำเร็จ

ฉันปิดใช้งานการป้อนอัตโนมัติ - ไม่เหมาะ แต่ทำให้ผู้ใช้สับสนน้อยลงมาก

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

พบคำตอบได้ที่นี่


-1

หากคุณใช้ jQuery คุณสามารถทำได้ในการส่งแบบฟอร์ม:

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
แม้ว่าวิธีนี้อาจได้ผล แต่ก็ไม่สมเหตุสมผลสำหรับรูปแบบที่ซับซ้อนมากขึ้น
origin1tech

-1

หากคุณต้องการให้มันเรียบง่ายเพียงแค่รับค่าโดยใช้จาวาสคริปต์

ในคอนโทรลเลอร์ js เชิงมุมของคุณ:

var username = document.getElementById ('ชื่อผู้ใช้'). value;


ฉันคิดว่าคุณไม่เข้าใจว่าปัญหาคืออะไร
aelor
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.