91 votes

Formulaires AngularJS - Valider les champs après que l'utilisateur a quitté le champ

EXEMPLE ICI : http://plnkr.co/edit/E6l6GOkKOEuVO1iz0fjU?p=preview

Avec AngularJS, je peux utiliser ng-pristine ou ng-dirty pour détecter si l'utilisateur a entré sur le terrain. Cependant, je veux faire la validation côté client seulement après que l'utilisateur a quitté la zone de champ. C'est parce que lorsqu'un utilisateur entre dans un domaine comme l'e-mail ou par téléphone, ils auront toujours une erreur renvoyé jusqu'à ce qu'ils ont terminé de taper leur adresse e-mail, et ce n'est pas une expérience utilisateur optimale.


Mise à JOUR:

Angulaire est maintenant livré avec une coutume flou de l'événement: https://docs.angularjs.org/api/ng/directive/ngBlur

92voto

user1506145 Points 116

À partir de la version 1.3.0, cela peut facilement être fait avec $touched , ce qui est vrai une fois que l'utilisateur a quitté le champ.

 <p ng-show="form.field.$touched && form.field.$invalid">Error</p>
 

https://docs.angularjs.org/api/ng/type/ngModel.NgModelController

75voto

pocesar Points 2577

Angulaire 1.3 a maintenant ng-modèle-options, et vous pouvez définir l'option d' { 'updateOn': 'blur'} par exemple, et vous pouvez même anti-rebond, lorsque l'utilisation est soit en tapant trop vite, ou si vous voulez économiser un peu cher DOM opérations (comme un modèle d'écriture à plusieurs DOM lieux et vous ne voulez pas un $digest cycle de passe sur chaque touche enfoncée)

https://docs.angularjs.org/guide/forms#custom-triggers et https://docs.angularjs.org/guide/forms#non-immediate-debounced-model-updates

Par défaut, toute modification du contenu de déclencher une mise à jour du modèle et la validation d'un formulaire. Vous pouvez remplacer ce comportement à l'aide de la ngModelOptions directive de lier uniquement à la liste des événements. I. e. ng-modèle-options="{ updateOn: 'flou' }" sera mise à jour et de valider seulement après le contrôle perd le focus. Vous pouvez définir plusieurs événements à l'aide d'un l'espace est délimité liste. I. e. ng-modèle-options="{ updateOn: 'mousedown blur' }"

Et anti-rebond

Vous pouvez retarder le modèle de mise à jour/validation à l'aide de la clé anti-rebond avec le ngModelOptions directive. Ce retard s'appliquera aussi à l' des analyseurs, des validateurs et des indicateurs de modèle comme $sale ou $vierges.

I. e. ng-modèle-options="{ anti-rebond: 500 }" attendez une demi-seconde depuis la dernière modification de contenu avant le déclenchement de la mise à jour du modèle et la validation d'un formulaire.

32voto

lambinator Points 2876

J'ai résolu ce problème en développant sur ce @jlmcdonald suggéré. J'ai créé une directive qui sera automatiquement appliquée à toutes les entrées et de sélectionner des éléments:

var blurFocusDirective = function () {
    return {
        restrict: 'E',
        require: '?ngModel',
        link: function (scope, elm, attr, ctrl) {
            if (!ctrl) {
                return;
            }

            elm.on('focus', function () {
                elm.addClass('has-focus');

                scope.$apply(function () {
                    ctrl.hasFocus = true;
                });
            });

            elm.on('blur', function () {
                elm.removeClass('has-focus');
                elm.addClass('has-visited');

                scope.$apply(function () {
                    ctrl.hasFocus = false;
                    ctrl.hasVisited = true;
                });
            });

            elm.closest('form').on('submit', function () {
                elm.addClass('has-visited');

                scope.$apply(function () {
                    ctrl.hasFocus = false;
                    ctrl.hasVisited = true;
                });
            });

        }
    };
};

app.directive('input', blurFocusDirective);
app.directive('select', blurFocusDirective);

Cela va ajouter de la has-focus et has-visited des classes de différents éléments que l'utilisateur se concentre/visites les éléments. Vous pouvez ensuite ajouter ces classes à vos règles CSS pour afficher les erreurs de validation:

input.has-visited.ng-invalid:not(.has-focus) {
    background-color: #ffeeee;   
}

Cela fonctionne bien dans le fait que les éléments de toujours obtenir $propriétés non valides, etc, mais le CSS peut être utilisé pour donner à l'utilisateur une meilleure expérience.

16voto

nicholas Points 2051

J'ai réussi à faire cela avec un peu simple de CSS. Cela nécessite que les messages d'erreur soient frères de l'entrée à laquelle ils se rapportent et qu'ils ont une classe de error .

 :focus ~ .error {
    display:none;
}
 

Une fois ces deux conditions remplies, tout message d'erreur lié à un champ de saisie ciblé sera masqué, ce que je pense que angularjs devrait faire de toute façon. On dirait un oubli.

4voto

grahammelcher Points 51

Je n'ai pas assez de réputation pour commenter @lambinator de la solution afin d'écrire mon commentaire ici.

J'ai été d'obtenir l'erreur suivante avec sa solution dans angular.js 1.2.4:

Erreur: [$rootScope:inprog] $digest déjà en cours

Je ne sais pas si j'ai fait quelque chose de mal ou si c'est un changement dans angulaire, mais de supprimer le champ.$appliquer de l'résolu le problème et les classes et/ou les états sont toujours mis à jour.

Si vous assistons également à cette erreur, donner à la suite de l'essayer:

var blurFocusDirective = function () {
  return {
    restrict: 'E',
    require: '?ngModel',
    link: function (scope, elm, attr, ctrl) {
      if (!ctrl) {
        return;
      }
      elm.on('focus', function () {
        elm.addClass('has-focus');
        ctrl.$hasFocus = true;
      });

      elm.on('blur', function () {
        elm.removeClass('has-focus');
        elm.addClass('has-visited');
        ctrl.$hasFocus = false;
        ctrl.$hasVisited = true;
      });

      elm.closest('form').on('submit', function () {
        elm.addClass('has-visited');

        scope.$apply(function () {
          ctrl.hasFocus = false;
          ctrl.hasVisited = true;
        });
      });
    }
  };
};
app.directive('input', blurFocusDirective);
app.directive('select', blurFocusDirective);

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X