Solution de contournement de remplissage automatique du navigateur AngularJS à l'aide d'une directive

111

Lorsque vous soumettez un formulaire dans AngularJS et utilisez la fonctionnalité de mémorisation du mot de passe du navigateur, et lors d'une tentative de connexion ultérieure, vous laissez le navigateur remplir le formulaire de connexion avec le nom d'utilisateur et le mot de passe, le $scopemodèle ne sera pas modifié en fonction de la saisie automatique.

Le seul hack sale que j'ai trouvé est d'utiliser la directive suivante:

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

Le problème est que le ngModel.$setViewValue(element.val());ne modifie pas le modèle ni la vue en fonction de la element.val()valeur renvoyée. Comment puis-je y parvenir?

lucassp
la source
Ce code semble correct à première vue ... mais où est le reste (balisage, etc.)? Avez-vous un violon ou un plunk que nous pouvons voir?
Ben Lesh
Voici le plunk : plnkr.co/edit/CHrBAVU9Ycl2ex2DRr6R Je ne sais pas si cela fonctionne directement sur plunker car il fonctionne dans une iframe.
lucassp
1
Vous n'avez pas besoin de définir. $ Apply à l'intérieur du $ timeout d'angular. Vous pourriez en avoir besoin dans window.setTimeout natif. Mais c'est une meilleure idée d'utiliser celle angulaire.
gorpacrate
1
Il existe un correctif polyfill "officiel" de Angular dev tbosch pour ce problème. Veuillez consulter les détails dans la réponse stackoverflow.com/a/25687396/3009639 ci-dessous.
orszaczky
Malheureusement, le correctif "officiel" est abandonware et ne fonctionne pas dans de nombreux navigateurs. Des problèmes ont été classés mais ne sont pas résolus, donc la recherche se poursuit ...
cyberwombat

Réponses:

45

Apparemment, il s'agit d'un problème connu avec Angular et est actuellement ouvert

Je ne sais pas ce que vous pourriez faire ici en plus d'une sorte de travail comme vous essayez. Il semble que vous êtes sur la bonne voie. Je n'ai pas pu faire en sorte que mon navigateur essaie de se souvenir d'un mot de passe pour votre plunk, donc je ne suis pas sûr que cela fonctionnera, mais jetez un œil:

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>

Je pense que vous avez juste besoin de simplifier un peu votre approche. La seule chose que je recommande vraiment est de vérifier ngModel.$pristineet de vous assurer que vous n'écrasez pas les entrées d'un utilisateur médiocre. De plus, 3 secondes, c'est probablement trop long. Vous ne devriez pas avoir à appeler $ apply () dans un $ timeout, BTW, il devrait mettre en file d'attente un $ digest pour vous automatiquement.

Le vrai hic: votre navigateur battra-t-il Angular à l'exécution? Et mon navigateur?

C'est probablement une guerre impossible à gagner, c'est pourquoi Angular (ou Knockout) n'a pas été en mesure de la résoudre facilement. Il n'y a aucune garantie de l'état des données dans votre entrée au moment de l'exécution initiale de la directive. Pas même au moment de l'initialisation d'Angular ... C'est donc un problème délicat à résoudre.

Ben Lesh
la source
1
Bon point à propos de $ Pristine. Eh bien, 3 secondes sont là juste à des fins de test. La boîte de dialogue "Enregistrer le mot de passe" semble fonctionner sur Safari. C'est un autre problème sur lequel je dois enquêter.
lucassp
Trompez-le simplement avec le stockage local. :) ... Je vais continuer à y penser. Mais j'ai des doutes sur la faisabilité de faire fonctionner le remplissage automatique avec des liaisons bidirectionnelles.
Ben Lesh
Oui, mais j'ai encore besoin de pouvoir mettre à jour le modèle à partir d'une directive pour que cela fonctionne.
lucassp
1
Je plaisantais à propos de localStorage, vous ne voudriez pas y garder les mots de passe.
Ben Lesh
1
Cela ne fonctionnera pas avec Safari et le remplissage automatique de la carte de crédit, car ce remplissage automatique est déclenché à tout moment par l'utilisateur
Dallas Clark
35

Voici une solution beaucoup moins hacky que les autres solutions présentées et qui est sémantiquement saine 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);
    }
  };
});

Ensuite, vous attachez simplement la directive à votre formulaire:

<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>
Ézéchiel Victor
la source
2
Celui-ci a fonctionné. Nous avons essayé la plupart des solutions ci-dessus sans aucun résultat. Merci!!! Le résultat est sur mobbr.com
Patrick Savalle du
1
Comme cela utilise jQuery, il ne devrait pas fonctionner sans jQuery.
Quinn Strahl
1
Nous voici en 2018 et c'est toujours le correctif. Merci Ezekiel!
Scott Manny
35

Vous n'avez pas besoin d'utiliser un $timeoutou quelque chose comme ça. Vous pouvez utiliser un système d'événements.

Je pense que c'est plus angulaire et ne dépend pas de jQuery ou de la capture d'événements personnalisés.

Par exemple sur votre gestionnaire d'envoi:

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

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

Et puis vous pouvez avoir une autofilldirective comme celle-ci:

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

Enfin, votre HTML sera comme:

<input type="text" name="username" ng-model="user.id" autofill="autofill"/>
bekos
la source
14
Dans mon cas, le bouton d'envoi est désactivé lorsque les entrées sont vides.
gorpacrate
4
N'avez-vous jamais de problème avec cela car il est asynchrone? où l'appel de connexion au serveur part déjà avant que l'événement ne soit répliqué et que la directive ait eu le temps de mettre à jour la portée?
Sander
12

Plus besoin de pirater! Angular dev tbosch a créé un polyfill qui déclenche un événement de modification lorsque le navigateur modifie les champs du formulaire sans déclencher d'événement de modification:

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

Pour l'instant, ils ne l'intégreront pas dans le code Angular, car il s'agit d'un correctif pour le navigateur, et fonctionne également sans Angular (par exemple pour les applications jQuery simples).

"Le polyfill vérifiera les modifications lors du chargement du document et également lorsqu'une entrée est laissée (uniquement sous la même forme). Cependant, vous pouvez déclencher la vérification manuellement si vous le souhaitez.

Le projet comporte des tests unitaires ainsi que des tests semi-automatiques, nous avons donc enfin un endroit pour collecter tous les différents cas d'utilisation avec les paramètres de navigateur requis.

Remarque: ce polyfill fonctionne avec les applications AngularJS simples, avec les applications AngularJS / jQuery mais aussi avec les applications jQuery simples qui n'utilisent pas Angular. "

Il peut être installé avec:

bower install autofill-event --save

Ajoutez le script autofill-event.js après jQuery ou Angular dans votre page.

Cela fera ce qui suit:

  • après DOMContentLoaded: vérifiez tous les champs de saisie
  • il reste un champ: vérifiez tous les autres champs du même formulaire

API (pour déclencher manuellement la vérification):

  • $el.checkAndTriggerAutoFillEvent(): Exécute la vérification de tous les éléments DOM dans l'élément jQuery / jQLite donné.

Comment ça fonctionne

  1. Souvenez-vous de toutes les modifications apportées aux éléments d'entrée par l'utilisateur (à l'écoute des événements de modification) et également par JavaScript (en interceptant $ el.val () pour les éléments jQuery / jQLite). Cette valeur modifiée est stockée sur l'élément dans une propriété privée.

  2. Vérification d'un élément pour le remplissage automatique: Comparez la valeur actuelle de l'élément avec la valeur mémorisée. Si c'est différent, déclenchez un événement de modification.

Dépendances

AngularJS ou jQuery (fonctionne avec l'un ou les deux)

Plus d'informations et source sur la page github .

Le problème angulaire original n ° 1460 sur Github peut être lu ici.

Orszaczky
la source
2
Cela ne fonctionne pas pour mes cas. checkAndTriggerAutoFillEvent () est déclenché et génère des événements, mais AngularJS ne met jamais à jour ses modèles et pense que les champs sont vides.
Splaktar
Je n'ai eu aucun problème avec ce polyill. Si vous ne pouvez pas le faire fonctionner correctement, vous devez créer une question distincte comprenant du code. Si vous trouvez un bug, vous devriez vérifier les tickets sur github ou en ouvrir un nouveau.
orszaczky
Oui, je pense que c'est lié à ce bug: github.com/tbosch/autofill-event/issues/11
Splaktar
1
ngModelOptionscombiné avec autofill-eventsignifie que vous pouvez désormais le spécifier changecomme l'un des updateOnévénements pour vous assurer que votre modèle est correctement synchronisé.
morloch
10

Code sale, vérifiez si le problème https://github.com/angular/angular.js/issues/1460#issuecomment-18572604 est résolu avant d'utiliser ce code. Cette directive déclenche des événements lorsque le champ est rempli, pas seulement avant de soumettre (c'est nécessaire si vous devez gérer l'entrée avant de soumettre)

 .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_
la source
5

Cela ressemble à une solution claire et directe. Aucun jQuery nécessaire.

METTRE À JOUR:

  • Le modèle est mis à jour uniquement lorsque la valeur du modèle n'est pas égale à la valeur d'entrée réelle.
  • La vérification ne s'arrête pas au premier remplissage automatique. Dans le cas où vous souhaitez utiliser un autre compte par exemple.

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
la source
4
+1 bonne solution, similaire à ce que j'ai proposé. Le seul ajout que je suggérerais est de vérifier d'abord si le modèle est $pristineavant de le changer, puis après l'avoir changé, conserver son $pristineétat. Sinon, vous constaterez que si un formulaire est chargé sans données de remplissage automatique, la directive ci-dessus mettra toujours à jour le modèle et le rendra par la suite dirtymême si le contrôle de formulaire doit toujours être considéré comme intact. exemple ici, en utilisant votre directive. J'ai commenté le code que j'ajouterais: jsfiddle.net/OACDesigns/L8Sja/4
OACDesigns
1
aussi, je pense que scope:truedevrait êtrescope:{}
OACDesigns
4

Solution 1 [Utilisation de $ timeout]:

Directif:

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>

Solution 2 [Utilisation d'événements angulaires]:

Réf: réponse de Becko

Directif:

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>

Solution 3 [Utilisation des appels de méthode de relais]:

Directif:

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
la source
2
La solution 1 a très bien fonctionné pendant un certain temps, mais maintenant sur angularjs 1.4.9 elle ne fonctionne plus. L'archivage model.$validde la directive renvoie vrai avant et après $setViewValue, mais l'élément est toujours avec la ng-invalidclasse
John
4

Eh bien, le moyen le plus simple est d'émuler le comportement du navigateur, donc s'il y a un problème avec l'événement de changement, lancez-le vous-même. Beaucoup plus simple.

Directif:

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>

Vous pouvez faire quelques variantes, comme mettre la directive sur le formulaire et déclencher l'événement sur toutes les entrées avec la classe .dirty lors de la soumission du formulaire.

pedroassis
la source
3

C'est la manière jQuery:

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

C'est la manière angulaire:

 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
la source
2
Voie complètement non angulaire.
gorpacrate
1
@gorpacrate: Maintenant, vérifiez-le de manière angulaire.
Nishchit Dhanani
2
Les onglets de Angular Way ont trop d'espaces. Je plaisante. J'adore le défilement horizontal.
Daniel Birowsky Popeski
cela ne fonctionne pas en angulaire car il n'y a pas de déclencheur de fonction sur l'élément. Je pense que cela nécessiterait d'inclure jquery
Tomas
1
triggerHandler('input')devrait être ok si vous n'avez pas jquery complet
Mutmatt
1

Voici une autre solution de contournement qui est moins piratée, mais nécessite du code supplémentaire dans le contrôleur.

HTML:

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

Directive (CoffeeScript):

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

Manette:

controllers.controller 'FormController', [->
    $scope.submitForm = ->
        username = $scope.getUsername?() ? $scope.username
        # HTTP stuff...
]
coup
la source
Vous l'avez en JavaScript vanille?
f1lt3r
CoffeeScript.org fournit un traducteur: fait ici
jab
1

C'est la seule solution que j'ai trouvée qui a permis à toutes mes validations Angular de fonctionner comme prévu, y compris la désactivation / l'activation du bouton d'envoi. S'installe avec bower et 1 balise de script. Bazinga!

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

Roland Hordos
la source
1
ce remplissage poly ne correspond pas à un bouton d'envoi / une liaison d'entrée à l'état du formulaire. à moins que vous ne cliquiez sur la page à n'importe quel point où vous souhaitez déclencher un condensé (il semble que l'action déclenche le navigateur pour faire un vrai remplissage), alors le bouton devient activer. Page de test avec tests manuels
e-cloud
1

Changer la valeur du modèle au lieu d'utiliser une fonction de délai d'expiration a fonctionné pour moi.

Voici mon 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
la source
1

Solution de contournement en une ligne dans le gestionnaire de soumission (nécessite jQuery):

if (!$scope.model) $scope.model = $('#input_field').val();
archpollux
la source
Ce n'est pas vraiment une ligne unique si c'est dans une directive, ce qui devrait certainement l'être.
isherwood
0

Je force un $ setValue (val ()) lors de la soumission: (cela fonctionne sans 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
la source
0

Je suis très nouveau sur Angularjs, mais j'ai trouvé une solution simple à ce problème => Forcer Angular à réévaluer l'expression ... en la changeant! (bien sûr, vous devez vous souvenir de la valeur initiale pour revenir à l'état initial) Voici comment cela se passe dans la fonction de votre contrôleur pour soumettre le formulaire:

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

où bien sûr, la valeur entrée dans votre saisie de mot de passe a été définie par Windows et non par l'utilisateur.

Le Neveu
la source
0

Vous pouvez essayer ce code:

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
la source
0

Une modification mineure à cette réponse ( https://stackoverflow.com/a/14966711/3443828 ): utilisez un $ intervalle au lieu d'un $ timeout pour ne pas avoir à courir le navigateur.

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
la source
0

C'est la solution que j'ai fini par utiliser dans mes formulaires.

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

Et le modèle du formulaire sera

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

De cette façon, j'ai pu exécuter tous les analyseurs / formateurs que j'ai sur mon ng-model et avoir la fonctionnalité d'envoi transparente.

Anirudhan J
la source
0

Solution sans directives:

.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
la source
0

Il s'agit d'une solution simple qui fonctionne pour tous les cas que j'ai testés à la fois dans Firefox et Chrome. Notez qu'avec la première réponse (directive w / timeout), j'ai eu des problèmes avec -

  • Boutons Précédent / Suivant du navigateur, ne relancez pas les événements de chargement de page (donc le correctif ne s'applique pas)
  • Chargement des informations d'identification quelque temps après le chargement de la page. Par exemple, dans Firefox, double-cliquez sur la boîte de connexion et sélectionnez parmi les informations d'identification stockées.
  • Besoin d'une solution qui se met à jour avant l'envoi du formulaire car je désactive le bouton de connexion jusqu'à ce qu'une entrée valide soit fournie

Ce correctif est évidemment très stupide et piraté, mais cela fonctionne 100% du temps -

function myScope($scope, $timeout) {
    // ...
    (function autoFillFix() {
        $timeout(function() { 
            $('#username').trigger('change'); 
            $('#password').trigger('change'); 
            autoFillFix(); }, 500);                    
    })();
}
Richard Nichols
la source
1
pourrait remplacer $timeoutpar $intervalpour donner un peu plus de contexte aux futurs développeurs et se débarrasser des appels récursifs étranges qui s'y
déroulent
0

Aucune de ces solutions n'a fonctionné pour mon cas d'utilisation. J'ai quelques champs de formulaire qui utilisent ng-change pour surveiller les changements. L'utilisation $watchn'est d'aucune aide car elle n'est pas déclenchée par la saisie automatique. Comme je n'ai pas de bouton d'envoi, il n'y a pas de moyen facile d'exécuter certaines des solutions et je n'ai pas réussi à utiliser les intervalles.

J'ai fini par désactiver le remplissage automatique - pas idéal mais beaucoup moins déroutant pour l'utilisateur.

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

J'ai trouvé la réponse ici

cyberwombat
la source
-1

Si vous utilisez jQuery, vous pouvez le faire en soumettant le formulaire:

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
la source
1
Bien que cela puisse fonctionner, ce n'est pas raisonnable pour les formulaires plus complexes.
origin1tech
-1

Si vous voulez rester simple, obtenez simplement la valeur en utilisant javascript

Dans votre contrôleur angular js:

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

user361697
la source
Je pense que vous ne comprenez pas quel est le problème
aelor