wake-up-neo.net

Angularjs Chrome Autocomplete-Dilemma

Ich habe ein einfaches Anmeldeformular, das nur peachy funktioniert, wenn Sie nicht die automatische Vervollständigungsfunktion von Chrome verwenden. 

Wenn Sie mit der Eingabe beginnen und die Funktion zum automatischen Vervollständigen verwenden und Ihr Kennwort automatisch ausgefüllt wird, hat mein anglejs-Modell keinen Wert für das Kennwort.

Ich habe versucht, die automatische Vervollständigung abzuschalten, indem ich das Attribut auf das Formular autocomplete="off" gesetzt habe. Dies scheint jedoch keine Auswirkung zu haben.

Wie kann ich entweder: 1. Stellen Sie sicher, dass ich den Wert erhalten kann, wenn jemand die automatische Vervollständigungsfunktion von Chrome verwendet? 2. Deaktivieren Sie die automatische Vervollständigungsfunktion von Chrome.

<form class="form-signin" name="form" ng-submit="login()" autocomplete="off">

        <h3>Login</h3>

        <input type="email" name="email" class="form-control" placeholder="Email address" ng-model="user.email" required autofocus>
        <input type="password" name="password" class="form-control" placeholder="Password" ng-model="user.password" required>

        <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>

 </form>
38
Catfish

Von dem im Kommentar hinzugefügten Link: Github Issue

// Due to browsers issue, it's impossible to detect without a timeout any changes of autofilled inputs
// https://github.com/angular/angular.js/issues/1460
// https://github.com/angular/angular.js/issues/1460#issuecomment-28662156
// Could break future Angular releases (if use `compile()` instead of `link())
// TODO support select
angular.module("app").config(["$provide", function($provide) {
    var inputDecoration = ["$delegate", "inputsWatcher", function($delegate, inputsWatcher) {
        var directive = $delegate[0];
        var link = directive.link;

        function linkDecoration(scope, element, attrs, ngModel){
            var handler;
            // By default model.$viewValue is equals to undefined
            if(attrs.type == "checkbox"){
                inputsWatcher.registerInput(handler = function(){
                    var value = element[0].checked;
                    // By default element is not checked
                    if (value && ngModel.$viewValue !== value) {
                        ngModel.$setViewValue(value);
                    }
                });
            }else if(attrs.type == "radio"){
                inputsWatcher.registerInput(handler = function(){
                    var value = attrs.value;
                    // By default element is not checked
                    if (element[0].checked && ngModel.$viewValue !== value) {
                        ngModel.$setViewValue(value);
                    }
                });
            }else{
                inputsWatcher.registerInput(handler = function(){
                    var value = element.val();
                    // By default value is an empty string
                    if ((ngModel.$viewValue !== undefined || value !== "") && ngModel.$viewValue !== value) {
                        ngModel.$setViewValue(value);
                    }
                });
            }

            scope.$on("$destroy", function(){
                inputsWatcher.unregisterInput(handler);
            });

            // Exec original `link()`
            link.apply(this, [].slice.call(arguments, 0));
        }

        // Decorate `link()` don't work for `inputDirective` (why?)
        /*
         directive.link = linkDecoration;
         */
        // So use `compile()` instead
        directive.compile = function compile(element, attrs, transclude){
            return linkDecoration;
        };
        delete directive.link;

        return $delegate;
    }];

    $provide.decorator("inputDirective", inputDecoration);
    $provide.decorator("textareaDirective", inputDecoration);
    //TODO decorate selectDirective (see binding "change" for `Single()` and `Multiple()`)
}]).factory("inputsWatcher", ["$interval", "$rootScope", function($interval, $rootScope){
    var INTERVAL_MS = 500;
    var promise;
    var handlers = [];

    function execHandlers(){
        for(var i = 0, l = handlers.length; i < l; i++){
            handlers[i]();
        }
    }

    return {
        registerInput: function registerInput(handler){
            if(handlers.Push(handler) == 1){
                promise = $interval(execHandlers, INTERVAL_MS);
            }
        },
        unregisterInput: function unregisterInput(handler){
            handlers.splice(handlers.indexOf(handler), 1);
            if(handlers.length == 0){
                $interval.cancel(promise);
            }
        }
    }
}]);
21
Pauli Price

Von: Developer.mozilla.org docs Turning_off_form_autocompletion

Wenn ein Autor das automatische Ausfüllen von Kennwortfeldern verhindern möchte auf Benutzerverwaltungsseiten, auf denen ein Benutzer ein neues Kennwort für .__ angeben kann. jemand anderes als sie selbst, autocomplete = "new-password" sollte .__ sein. angegeben, obwohl die Unterstützung dafür nicht in allen .__ implementiert wurde. Browser noch.

Also, was macht es für mich funktionieren:

  • setze autocomplete = "neues Passwort" im Passwortfeld
  • setze autocomplete = "off" im Feld "Benutzername".

Ich hoffe, dass es auch für dich funktioniert :)

12
ptgamr

Wie hier gesagt, https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form

Die Google Chrome-Benutzeroberfläche für automatisch vervollständigte Anforderungen variiert je nach ob die automatische Vervollständigung von Eingabeelementen sowie deren .__ deaktiviert ist. bilden. Insbesondere, wenn die automatische Vervollständigung eines Formulars auf "off" und ".__" eingestellt ist. Das Feld für die automatische Vervollständigung des Eingabeelements ist nicht festgelegt, und der Benutzer fragt Für Vorschläge zum automatischen Ausfüllen des Eingabeelements zeigt Chrome möglicherweise eine .__ an. Meldung, dass "Autovervollständigung für dieses Formular deaktiviert wurde." Auf der Andererseits, wenn sowohl das Formular als auch das Eingabeelement über die automatische Vervollständigung verfügen Wenn diese Option deaktiviert ist, zeigt der Browser diese Nachricht nicht an. Dafür Aus diesem Grund sollten Sie die automatische Vervollständigung für jede Eingabe mit .__ ausschalten. benutzerdefinierte automatische Vervollständigung.

Sie müssen autocomplete = "off" für form und input setzen.

Ich glaube nicht, dass dies mit AngularJS zusammenhängt

11
allenhwkim

Ich hatte das gleiche Problem und fand eine sehr einfache Lösung, die nur jQuery verwendet, um den Wert beim Senden zu ermitteln. In meinem Controller habe ich Folgendes:

$scope.username = "";
$scope.password = "";

$scope.login = function(){
    $scope.username = $("#username").val();
    $scope.password = $("#password").val();
    // Proceed as normal
};

Es gibt einige Nachteile, wenn Sie die Validierung durchführen müssen usw., aber ansonsten ist dies für kleinere Formulare wie diese ausreichend.

7
Dachande663

Sie können den Wert des E-Mail-Felds beobachten und jedes Mal, wenn sich der Wert in diesem Feld ändert, können Sie im Kennwortfeld ein "change" -Ereignis auslösen. Diese Ereignisse lösen die gesamte Magie des ng-Modells in diesem Feld aus und aktualisieren das Modell.

module.directive("autocompleteFor", function () {
    return {
        restrict: "A",
        link: function ($scope, $element, $attrs) {
            $scope.$watch($attrs.autocompleteFor, function () {
                $element.triggerHandler("change");
            })
        }
    }
});

Mit dieser Anweisung können Sie dieses Szenario wie folgt behandeln:

<input type="email" name="email" ng-model="user.email">
<input type="password" autocomplete-for="user.email" name="password" ng-model="user.password"   required>
                       -----------------------------
2
kfis

Um das Autocomplete/Autofill von einer Eingabe zu deaktivieren, geben Sie einfach Folgendes ein: - autocomplete = "false" anstelle von autocomplete = "off"!

2
Rafael Ferreira

Die folgende Anweisung hat für mich gearbeitet. Es ist einfach und sauber zu beheben. Hoffentlich hilft das!

Ref: AngularJS-Browser-Problemumgehung mithilfe einer Direktive

Hier ist eine Lösung, die weit weniger hackig ist als andere präsentierte Lösungen und semantisch solide AngularJS ist: VictorBlog.com

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 auto-filled 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 hängen Sie einfach die Direktive an Ihr Formular an:

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

eine alternative Lösung besteht darin, sich vom Formularelement zu befreien und stattdessen ng-form zu verwenden. Dadurch werden alle Browser-Eingriffe deaktiviert

<div ng-form="yourFormName" class="form-signin" ng-submit="login()">
1

Ich bekam eine andere Lösung, die ich hier noch nicht sehe. Nach dem, was ich gefunden habe, wird der Kennwortwert dem Modell (oder möglicherweise sogar der js-API) nicht angezeigt, bis der Benutzer mit der Seite interagiert. Durch Klicken auf die Anmeldeschaltfläche genügt die Interaktion, um den Wert verfügbar zu machen. Die Datenbindung wird früh genug durchgeführt, damit der Click-Handler auf der Schaltfläche auf das Kennwort vom Modell aus zugreifen kann. Wenn ich also feststellen konnte, dass der Browser automatisch gefüllt wurde, könnte ich die Login-Schaltfläche aktivieren, obwohl mein Modell noch nicht aktualisiert wurde. Also habe ich einen einfachen Hilfsdienst geschrieben, um zu sehen, ob Chrome Eingaben automatisch gefüllt hat:

utilApp.service('autoFillDetectionService', [function () {
    return {
        hasAutoFillInputs: function () {
            try{
                return !!$(':-webkit-autofill').length;
            }
            catch (x) {
                // IE gets here, it/jquery complains about an invalid pseudo-class
                return false;
            }
        }
    };
}]);

Vom Login-Controller habe ich ein Intervall, in dem überprüft wird, ob Eingabefelder als automatisches Ausfüllen markiert sind, und aktivieren Sie in diesem Fall die Login-Schaltfläche.

0
bmm6o

Meine Lösung für Chrome 35.0, Firefox 30.0, Winkel 1.2.18 (Anmeldeseite mit Kennwortmanager, automatisches Ausfüllen, Winkelmethode und Weiterleitung):

Woher weiß der Browser, wann er den Benutzer auffordert, das Passwort zu speichern?

0
110maor

--- NICHT MEHR RELEVANT ---

Ich konnte Autovervollständigung deaktivieren (seltsamerweise), indem ich Folgendes hinzufügte.

<form ... novalidate>
<input ... formnovalidate />

Verweise auf diesen Plunker

0
Cory Silva

Es könnte eine viel einfachere Lösung für das Problem sein. 

  1. Angularjs konnte den Wert nicht "sehen" 
  2. Nehmen Sie den Wert über DOM (jQuery) und legen Sie ihn dann wieder in Angularjs ab.

`` `

angular.module('someModule').directive('chromeAutofillHack', function()
{
    return {
        require: '^ngModel',
        restrict: 'A',
        priority: 500, // set higher priority then other custom directives
        link: function(scope, element, attrs , ngModelCtrl)
        {
            ngModelCtrl.$parsers.unshift(function(email)
            {
                if (!email) { // only do this when angular think there is no value
                    email = $(element).val();
                    ngModel.$setViewValue(email);
                }
                return email;
            });
        }
    };
});

`` `

0
Joel Chu

In meinem Fall setze ich in Form und Eingabe die Eigenschaft autocomplete = "off".

<form autocomplete="off">
   <input type="text" autocomplete="off">
</form>
0
Kate.spot

Alte Frage, aber wie auch immer

Ich bin auf das gleiche Problem gestoßen und habe eine kleine "Hack" -Lösung. Dieses Problem trat an vielen verschiedenen Orten in meiner App auf. Daher habe ich eine Richtlinie zur Wiederverwendbarkeit erstellt.

module.directive("fakeAutocomplete", [
  function () {
    return {
      restrict: "EA",
      replace: true,
      template: "<div><input/><input type=\"password\"/></div>",
      link: function (scope, elem, attrs) {
        elem.css({
          "overflow": "hidden",
          "width": "0px",
          "height": "0px"
        });
      }
    }
  }
]);

Und einfach hinzufügen

<fake-autocomplete></fake-autocomplete>

Am Anfang Ihres Formulars erkennt der Browser die gefälschten Felder als diejenigen, die automatisch ausgefüllt werden sollten. Einfach display:none auf die Felder zu setzen scheint auch nicht mehr zu funktionieren, ich habe es getestet.

0
Louis Boux