Problemumgehung für das automatische Ausfüllen des AngularJS-Browsers mithilfe einer Direktive

111

Wenn Sie ein Formular in AngularJS senden und die Browser-Funktion $scopezum Speichern des Kennworts verwenden und bei einem nachfolgenden Anmeldeversuch den Browser das Anmeldeformular mit dem Benutzernamen und dem Kennwort ausfüllen lassen, wird das Modell nicht basierend auf dem automatischen Ausfüllen geändert.

Der einzige schmutzige Hack, den ich gefunden habe, ist die Verwendung der folgenden Anweisung:

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

Das Problem ist, dass ngModel.$setViewValue(element.val());weder das Modell noch die Ansicht basierend auf dem element.val()zurückgegebenen Wert geändert werden. Wie kann ich das erreichen?

lucassp
quelle
Dieser Code sieht auf den ersten Blick in Ordnung aus ... aber wo ist der Rest (Markup usw.)? Haben Sie eine Geige oder ein Plunk, die wir sehen können?
Ben Lesh
Hier ist der Plunk: plnkr.co/edit/CHrBAVU9Ycl2ex2DRr6R Ich bin nicht sicher, ob er direkt auf dem Plunker funktioniert, da er in einem Iframe ausgeführt wird.
Lucassp
1
Sie müssen keinen Gültigkeitsbereich festlegen. $ Wird innerhalb des $ Timeouts von Angular angewendet. Möglicherweise benötigen Sie es in nativem window.setTimeout. Aber es ist eine bessere Idee, Angulars zu verwenden.
Gorpacrate
1
Für dieses Problem gibt es eine "offizielle" Polyfill-Korrektur von Angular dev tbosch . Weitere Informationen finden Sie in der Antwort stackoverflow.com/a/25687396/3009639 unten.
Orszaczky
Leider ist das "offizielle" Update Abbruchware und funktioniert in vielen Browsern nicht. Probleme wurden eingereicht, aber nicht
behoben,

Antworten:

45

Anscheinend ist dies ein bekanntes Problem mit Angular und ist derzeit offen

Ich bin mir nicht sicher, was Sie hier tun könnten, abgesehen von irgendeiner Art von Arbeit, wie Sie es versuchen. Sie scheinen auf dem richtigen Weg zu sein. Ich konnte meinen Browser nicht dazu bringen, sich ein Passwort für Ihren Plunk zu merken, daher bin ich mir nicht sicher, ob dies funktionieren wird, aber schauen Sie sich Folgendes an:

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>

Ich denke, Sie müssen Ihren Ansatz nur ein wenig vereinfachen. Das einzige, was ich auf jeden Fall empfehlen kann, ist zu überprüfenngModel.$pristine , ob Sie die Eingaben eines schlechten Benutzers nicht überschreiben. Auch 3 Sekunden sind wahrscheinlich zu lang. Sie sollten $ apply () nicht in einem $ timeout aufrufen müssen, übrigens sollte es automatisch einen $ Digest für Sie in die Warteschlange stellen.

Der wahre Haken: Wird Ihr Browser Angular bei der Ausführung schlagen? Was ist mit meinem Browser?

Dies ist wahrscheinlich ein nicht gewinnbarer Krieg, weshalb Angular (oder Knockout) ihn nicht ohne weiteres lösen konnte. Es gibt keine Garantie für den Status der Daten in Ihrer Eingabe zum Zeitpunkt der ersten Ausführung der Richtlinie. Nicht einmal zum Zeitpunkt der Initialisierung von Angular ... Es ist also ein schwieriges Problem, es zu lösen.

Ben Lesh
quelle
1
Guter Punkt über $ makellos. Nun, 3 Sekunden sind nur zu Testzwecken da. Das Dialogfeld "Passwort speichern" scheint auf Safari zu funktionieren. Das ist ein weiteres Problem, das ich untersuchen muss.
Lucassp
Täuschen Sie ihn einfach mit lokaler Lagerung. :) ... Ich werde weiter darüber nachdenken. Ich habe jedoch Zweifel an der Machbarkeit, dass das automatische Ausfüllen mit Zwei-Wege-Bindungen funktioniert.
Ben Lesh
Ja, aber ich muss das Modell noch von einer Direktive aus aktualisieren können, damit es funktioniert.
Lucassp
1
Ich habe mich über localStorage lustig gemacht, Sie möchten dort keine Passwörter behalten.
Ben Lesh
1
Dies funktioniert nicht mit Safari und dem automatischen Ausfüllen der Kreditkarte, da dieses automatische Ausfüllen jederzeit vom Benutzer ausgelöst wird
Dallas Clark
35

Hier ist eine Lösung, die weitaus weniger hackig ist als andere vorgestellte Lösungen und semantisch einwandfrei ist. 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);
    }
  };
});

Dann fügen Sie einfach die Direktive Ihrem Formular bei:

<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>
Hesekiel Victor
quelle
2
Dieser hat funktioniert. Wir haben die meisten der oben genannten Versuche ohne Ergebnis versucht. Vielen Dank!!! Das Ergebnis ist auf mobbr.com
Patrick Savalle
1
Da dies jQuery verwendet, wird nicht erwartet, dass es ohne jQuery funktioniert.
Quinn Strahl
1
Hier sind wir im Jahr 2018 und dies ist immer noch die Lösung. Danke Hesekiel!
Scott Manny
35

Sie müssen kein $timeoutoder ähnliches verwenden. Sie können ein Ereignissystem verwenden.

Ich denke, es ist eher angularisch und hängt nicht von jQuery oder benutzerdefiniertem Ereignisfang ab.

Zum Beispiel auf Ihrem Submit-Handler:

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

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

Und dann können Sie eine autofillAnweisung wie diese haben:

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

Schließlich wird Ihr HTML wie folgt aussehen:

<input type="text" name="username" ng-model="user.id" autofill="autofill"/>
bekos
quelle
14
In meinem Fall ist die Schaltfläche "Senden" deaktiviert, wenn die Eingaben leer sind.
Gorpacrate
4
Haben Sie nie Probleme damit, da es asynchron ist? Wohin führt der Anmeldeaufruf an den Server bereits, bevor das Ereignis repliziert wurde und die Direktive Zeit hatte, den Bereich zu aktualisieren?
Sander
12

Sie müssen nicht mehr hacken! Angular Dev Tbosch hat eine Polyfüllung erstellt, die ein Änderungsereignis auslöst, wenn der Browser Formularfelder ändert, ohne ein Änderungsereignis auszulösen:

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

Im Moment wird dies nicht in den Angular-Code integriert, da dies ein Bugfix für den Browser ist und auch ohne Angular funktioniert (z. B. für einfache jQuery-Apps).

"Die Polyfüllung prüft beim Laden von Dokumenten und auch dann, wenn eine Eingabe übrig bleibt (nur in derselben Form), auf Änderungen. Sie können die Prüfung jedoch manuell auslösen, wenn Sie möchten.

Das Projekt umfasst sowohl Komponententests als auch halbautomatische Tests, sodass wir endlich die Möglichkeit haben, die verschiedenen Anwendungsfälle zusammen mit den erforderlichen Browsereinstellungen zu erfassen.

Bitte beachten Sie: Diese Polyfüllung funktioniert mit einfachen AngularJS-Apps, mit AngularJS / jQuery-Apps, aber auch mit einfachen jQuery-Apps, die Angular nicht verwenden. "

Es kann installiert werden mit:

bower install autofill-event --save

Fügen Sie das Skript autofill-event.js nach hinzu jQuery oder Angular zu Ihrer Seite hinzu.

Dies wird Folgendes bewirken:

  • nach DOMContentLoaded: Überprüfen Sie alle Eingabefelder
  • Es bleibt ein Feld übrig: Überprüfen Sie alle anderen Felder in derselben Form

API (um die Prüfung manuell auszulösen):

  • $el.checkAndTriggerAutoFillEvent(): Führen Sie die Prüfung für alle DOM-Elemente im angegebenen jQuery / jQLite-Element aus.

Wie es funktioniert

  1. Merken Sie sich alle Änderungen an Eingabeelementen durch den Benutzer (auf Änderungsereignisse achten) und auch durch JavaScript (durch Abfangen von $ el.val () für jQuery / jQLite-Elemente). Dieser geänderte Wert wird auf dem Element in einer privaten Eigenschaft gespeichert.

  2. Überprüfen eines Elements auf automatische Füllung: Vergleichen Sie den aktuellen Wert des Elements mit dem gespeicherten Wert. Wenn es anders ist, lösen Sie ein Änderungsereignis aus.

Abhängigkeiten

AngularJS oder jQuery (funktioniert mit einem oder beiden)

Weitere Infos und Quelle auf der Github-Seite .

Die Original Angular Issue # 1460 auf Github kann hier gelesen werden.

orszaczky
quelle
2
Dies funktioniert in meinen Fällen nicht. checkAndTriggerAutoFillEvent () wird ausgelöst und generiert Ereignisse, aber AngularJS aktualisiert niemals seine Modelle und denkt, dass die Felder leer sind.
Splaktar
Ich hatte keine Probleme mit dieser Polyille. Wenn Sie es nicht richtig zum Laufen bringen können, sollten Sie eine separate Frage mit etwas Code erstellen. Wenn Sie einen Fehler finden, sollten Sie die Tickets auf github überprüfen oder einen neuen öffnen.
Orszaczky
Ja, ich denke, dass es mit diesem Fehler zusammenhängt: github.com/tbosch/autofill-event/issues/11
Splaktar
1
ngModelOptionskombiniert mit autofill-eventMitteln, die Sie jetzt changeals eines der updateOnEreignisse angeben können, um sicherzustellen, dass Ihr Modell korrekt synchronisiert ist.
Morloch
10

Überprüfen Sie, ob das Problem https://github.com/angular/angular.js/issues/1460#issuecomment-18572604 behoben ist, bevor Sie diesen Code verwenden. Diese Anweisung löst Ereignisse aus, wenn das Feld gefüllt ist, nicht nur vor dem Senden (dies ist erforderlich, wenn Sie die Eingabe vor dem Senden verarbeiten müssen).

 .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);
                   }
               };
});
OZ_
quelle
5

Scheint eine klare, geradlinige Lösung zu sein. Keine jQuery erforderlich.

AKTUALISIEREN:

  • Das Modell wird nur aktualisiert, wenn der Modellwert nicht dem tatsächlichen Eingabewert entspricht.
  • Die Überprüfung hört beim ersten automatischen Ausfüllen nicht auf. Für den Fall, dass Sie beispielsweise ein anderes Konto verwenden möchten.

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();
        }
    }
}]);
gorpacrate
quelle
4
+1 gute Lösung, ähnlich wie ich sie mir ausgedacht habe. Die einzige Ergänzung, die ich vorschlagen würde, ist, zuerst zu überprüfen, ob sich das Modell befindet, $pristinebevor Sie es ändern, und dann nach dem Ändern den $pristineStatus beizubehalten. Andernfalls werden Sie feststellen, dass die obige Anweisung das Modell weiterhin aktualisiert und anschließend erstellt, wenn ein Formular ohne Daten zum automatischen Ausfüllen geladen wird dirty, obwohl das Formularsteuerelement weiterhin als unberührt betrachtet werden sollte. Beispiel hier mit Ihrer Direktive. Ich habe den Code auskommentiert
OACDesigns
1
Ich denke auch, dass es scope:truesein solltescope:{}
OACDesigns
4

Lösung 1 [Verwenden von $ timeout]:

Richtlinie:

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>

Lösung 2 [Verwenden von Winkelereignissen]:

Ref: Beckos Antwort

Richtlinie:

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>

Lösung 3 [Verwenden von Relay-Methodenaufrufen]:

Richtlinie:

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>
Robin Rizvi
quelle
2
Lösung 1 hat eine Zeit lang sehr gut funktioniert, aber jetzt funktioniert sie unter anglejs 1.4.9 nicht mehr. Das Einchecken der model.$validDirektive gibt sowohl vorher als auch nachher true zurück $setViewValue, aber das Element ist immer noch in der ng-invalidKlasse
John
4

Am einfachsten ist es, das Verhalten des Browsers zu emulieren. Wenn also ein Problem mit dem Änderungsereignis auftritt, lösen Sie es einfach selbst aus. Viel einfacher.

Richtlinie:

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>

Sie können einige Variationen ausführen, z. B. die Anweisung in das Formular einfügen und das Ereignis für alle Eingaben mit der Klasse .dirty beim Senden des Formulars auslösen.

Pedroassis
quelle
3

Dies ist jQuery Weg:

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

Dies ist Angular Weg:

 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 /> 
Nishchit Dhanani
quelle
2
Völlig nicht eckig.
Gorpacrate
1
@gorpacrate: Jetzt überprüfe es mit eckigem Weg.
Nishchit Dhanani
2
Die Registerkarten des Winkelwegs haben zu viele Leerzeichen. Ich mache nur Spaß. Ich liebe horizontales Scrollen.
Daniel Birowsky Popeski
Dies funktioniert nicht im Winkel, da es keinen Funktionsauslöser für das Element gibt. Ich denke, dies würde erfordern, jquery einzuschließen
Tomas
1
triggerHandler('input')sollte in Ordnung sein, wenn Sie nicht ausgewachsene jquery haben
Mutmatt
1

Hier ist eine weitere Problemumgehung, die weniger hackig ist, aber zusätzlichen Code im Controller erfordert.

HTML:

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

Richtlinie (CoffeeScript):

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

Regler:

controllers.controller 'FormController', [->
    $scope.submitForm = ->
        username = $scope.getUsername?() ? $scope.username
        # HTTP stuff...
]
Jab
quelle
Sie haben dies in Vanille JavaScript?
f1lt3r
CoffeeScript.org bietet einen Übersetzer: hier gemacht
Stich
1

Dies ist die einzige Lösung, die es mir ermöglicht hat, dass alle meine Angular-Validierungen wie geplant funktionieren, einschließlich der Schaltfläche zum Deaktivieren / Aktivieren der Übermittlung. Wird mit Laube und 1 Skript-Tag installiert. Bazinga!

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

Roland Hordos
quelle
1
Diese Poly-Füllung passt nicht zu einer Senden-Schaltfläche / Eingabe-Bindung an den Formularstatus. Wenn Sie nicht auf die Seite klicken, an der Sie einen Digest auslösen möchten (es scheint, dass die Aktion den Browser dazu veranlasst, eine echte Füllung durchzuführen), wird die Schaltfläche aktiviert. Testseite mit manuellen Tests
E-Cloud
1

Das Ändern des Modellwerts anstelle einer Timeout-Funktion hat bei mir funktioniert.

Hier ist mein Code:

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

Einzeilige Problemumgehung im Submit-Handler (erfordert jQuery):

if (!$scope.model) $scope.model = $('#input_field').val();
Archpollux
quelle
Es ist nicht wirklich ein Einzeiler, wenn es sich um eine Richtlinie handelt, die es auf jeden Fall sein sollte.
Isherwood
0

Ich erzwinge beim Senden einen $ setValue (val ()): (dies funktioniert ohne 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);
Malix
quelle
0

Ich bin sehr neu in Angularjs, aber ich habe eine einfache Lösung für dieses Problem gefunden => Angular zwingen, den Ausdruck neu zu bewerten ... indem ich ihn ändere! (Natürlich müssen Sie sich den Anfangswert merken, um zum Ausgangszustand zurückzukehren.) So geht es in Ihrer Controller-Funktion zum Senden des Formulars:

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

Dabei wurde der in Ihre Passworteingabe eingegebene Wert natürlich von Windows und nicht vom Benutzer festgelegt.

Le neveu
quelle
0

Sie können diesen Code ausprobieren:

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

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

Eine geringfügige Änderung dieser Antwort ( https://stackoverflow.com/a/14966711/3443828 ): Verwenden Sie ein $ -Intervall anstelle eines $ -Zeitlimits, damit Sie nicht mit dem Browser rennen müssen.

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
    }
  });
user3443828
quelle
0

Dies ist die Lösung, die ich letztendlich in meinen Formularen verwendet habe.

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

Und die Vorlage des Formulars wird sein

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

Auf diese Weise konnte ich alle Parser / Formatierer ausführen, die ich auf meinem ng-Modell habe, und die Übermittlungsfunktion transparent machen.

Anirudhan J.
quelle
0

Lösung ohne Richtlinien:

.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);
    }])
ReklatsMasters
quelle
0

Dies ist eine einfache Lösung, die für alle Fälle funktioniert, die ich sowohl in Firefox als auch in Chrome getestet habe. Beachten Sie, dass ich mit der Top-Antwort (Direktive mit Timeout) Probleme mit - hatte

  • Browser-Schaltflächen "Zurück / Vorwärts", Seitenladeereignisse nicht erneut auslösen (daher gilt das Update nicht)
  • Laden von Anmeldeinformationen einige Zeit nach dem Laden der Seite. Doppelklicken Sie beispielsweise in Firefox auf das Anmeldefeld und wählen Sie aus den gespeicherten Anmeldeinformationen aus.
  • Benötigen Sie eine Lösung, die vor dem Absenden des Formulars aktualisiert wird, da ich die Schaltfläche Anmelden deaktiviere, bis eine gültige Eingabe bereitgestellt wird

Dieses Update ist offensichtlich sehr dumm und hackig, aber es funktioniert 100% der Zeit -

function myScope($scope, $timeout) {
    // ...
    (function autoFillFix() {
        $timeout(function() { 
            $('#username').trigger('change'); 
            $('#password').trigger('change'); 
            autoFillFix(); }, 500);                    
    })();
}
Richard Nichols
quelle
1
könnte ersetzt $timeoutwerden $interval, um zukünftigen Entwicklern ein bisschen mehr Kontext zu geben und die seltsam aussehenden rekursiven Aufrufe loszuwerden, die dort stattfinden
Mutmatt
0

Keine dieser Lösungen funktionierte für meinen Anwendungsfall. Ich habe einige Formularfelder, die ng-change verwenden, um auf Änderungen zu achten. Die Verwendung $watchist keine Hilfe, da sie nicht durch das automatische Ausfüllen ausgelöst wird. Da ich keine Schaltfläche zum Senden habe, gibt es keine einfache Möglichkeit, einige der Lösungen auszuführen, und ich habe Intervalle nicht erfolgreich verwendet.

Am Ende habe ich das automatische Ausfüllen deaktiviert - nicht ideal, aber für den Benutzer viel weniger verwirrend.

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

Können Sie die Antwort hier

Cyberwombat
quelle
-1

Wenn Sie jQuery verwenden, können Sie dies beim Senden des Formulars tun:

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();
}
Hans Kerkhof
quelle
1
Obwohl dies möglicherweise funktioniert, ist es für komplexere Formulare nicht sinnvoll.
origin1tech
-1

Wenn Sie es einfach halten möchten, erhalten Sie den Wert einfach mit Javascript

In Ihrem Winkel-js-Controller:

var username = document.getElementById ('Benutzername'). value;

user361697
quelle
Ich denke, Sie verstehen nicht, was das Problem ist
aelor