Valider les champs après que l’utilisateur a quitté un champ

Avec AngularJS, je peux utiliser ng-pristine ou ng-dirty pour détecter si l’utilisateur est entré dans le champ. Cependant, je souhaite effectuer la validation côté client uniquement après que l’utilisateur a quitté la zone de champ. En effet, lorsqu’un utilisateur entre dans un champ tel que le courrier électronique ou le téléphone, il reçoit toujours une erreur jusqu’à ce qu’il ait terminé de taper son courrier électronique complet, ce qui ne constitue pas une expérience utilisateur optimale.

Exemple


METTRE À JOUR:

Angular est désormais livré avec un événement de flou personnalisé: https://docs.angularjs.org/api/ng/directive/ngBlur

Angular 1.3 a maintenant ng-model-options, et vous pouvez définir l’option sur { 'updateOn': 'blur'} par exemple, et vous pouvez même rebondir lorsque l’utilisation est trop rapide ou que vous voulez enregistrer une peu d’opérations DOM coûteuses (comme un modèle écrivant dans plusieurs emplacements DOM et vous ne voulez pas qu’un cycle $ digest se produise à chaque touche)

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

Par défaut, toute modification du contenu déclenchera une mise à jour du modèle et la validation du formulaire. Vous pouvez remplacer ce comportement à l’aide de la directive ngModelOptions pour lier uniquement la liste spécifiée d’événements. Ie ng-model-options = “{updateOn: ‘blur’}” ne sera mis à jour et valider que lorsque le contrôle aura perdu le focus. Vous pouvez définir plusieurs événements en utilisant une liste délimitée par des espaces. Ie ng-model-options = “{updateOn: ‘mousedown flou’}”

Et rebond

Vous pouvez retarder la mise à jour / validation du modèle en utilisant la clé debounce avec la directive ngModelOptions. Ce délai s’appliquera également aux parsingurs, validateurs et modèles tels que $ dirty ou $ pristine.

Cela signifie que ng-model-options = “{debounce: 500}” attendra une demi-seconde depuis le dernier changement de contenu avant de déclencher la mise à jour du modèle et la validation du formulaire.

A partir de la version 1.3.0, cela peut facilement être fait avec $touched , ce qui est vrai après que l’utilisateur a quitté le champ.

 

Error

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

J’ai résolu ce problème en développant ce que @jlmcdonald a suggéré. J’ai créé une directive qui serait automatiquement appliquée à tous les éléments d’entrée et de sélection:

 var blurFocusDirective = function () { return { ressortingct: '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 appenda des classes has-focus et has-visited à divers éléments au fur et à mesure que l’utilisateur concentre / visite les éléments. Vous pouvez ensuite append 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 la mesure où les éléments ont toujours des propriétés $ invalides, etc., mais le CSS peut être utilisé pour donner à l’utilisateur une meilleure expérience.

J’ai réussi à le faire avec un morceau de CSS assez simple. Cela nécessite que les messages d’erreur soient des frères et soeurs de l’entrée à laquelle ils se rapportent et qu’ils comportent une classe d’ error .

 :focus ~ .error { display:none; } 

Après avoir satisfait à ces deux exigences, cela masquera tout message d’erreur lié à un champ de saisie ciblé, ce que je pense que angularjs devrait faire de toute façon. Semble comme un oubli.

Cela semble être implémenté de manière standard dans les nouvelles versions angulars.

Les classes ng-untouched et ng-touched sont définies respectivement avant et après que l’utilisateur se soit concentré sur un élément validé.

CSS

 input.ng-touched.ng-invalid { border-color: red; } 

En ce qui concerne la solution de @ lambinator … je recevais l’erreur suivante dans angular.js 1.2.4:

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

Je ne suis pas sûr si j’ai fait quelque chose de mal ou s’il s’agit d’un changement dans Angular, mais la suppression de la scope.$apply instructions scope.$apply résolu le problème et les classes / états sont toujours mis à jour.

Si vous rencontrez également cette erreur, essayez ceci:

 var blurFocusDirective = function () { return { ressortingct: '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); 

Il peut être utile d’écrire une directive personnalisée qui encapsule la méthode javascript blur () (et exécute une fonction de validation lorsqu’elle est déclenchée); Il y a un problème angular qui en comporte un exemple (ainsi qu’une directive générique pouvant se lier à d’autres événements non pris en charge de manière native par Angular):

https://github.com/angular/angular.js/issues/1277

Si vous ne voulez pas utiliser cette route, votre autre option serait de configurer $ watch sur le terrain, ce qui déclencherait une nouvelle validation lorsque le champ est rempli.

Pour aller plus loin dans les réponses données, vous pouvez simplifier l’étiquetage en utilisant des pseudo-classes CSS3 et ne marquer que les champs visités avec une classe pour retarder l’affichage des erreurs de validation jusqu’à ce que l’utilisateur ait perdu le focus:

(Exemple nécessite jQuery)

JavaScript

 module = angular.module('app.directives', []); module.directive('lateValidateForm', function () { return { ressortingct: 'AC', link: function (scope, element, attrs) { $inputs = element.find('input, select, textarea'); $inputs.on('blur', function () { $(this).addClass('has-visited'); }); element.on('submit', function () { $inputs.addClass('has-visited'); }); } }; }); 

CSS

 input.has-visited:not(:focus):required:invalid, textarea.has-visited:not(:focus):required:invalid, select.has-visited:not(:focus):required:invalid { color: #b94a48; border-color: #ee5f5b; } 

HTML

 

basé sur @nicolas répondre .. Pure CSS devrait faire l’affaire, il ne montrera que le message d’erreur sur le flou

  

This is not a valid email.

CSS

 .ng-invalid:focus ~ .bg-danger { display:none; } 

Voici un exemple utilisant ng-messages (disponible dans angular 1.3) et une directive personnalisée.

Le message de validation est affiché sur le flou pour la première fois que l’utilisateur quitte le champ de saisie, mais lorsqu’il corrige la valeur, le message de validation est immédiatement supprimé (plus flou).

JavaScript

 myApp.directive("validateOnBlur", [function() { var ddo = { ressortingct: "A", require: "ngModel", scope: {}, link: function(scope, element, attrs, modelCtrl) { element.on('blur', function () { modelCtrl.$showValidationMessage = modelCtrl.$dirty; scope.$apply(); }); } }; return ddo; }]); 

HTML

 
name is required name is too short name is too long

PS N’oubliez pas de télécharger et d’inclure ngMessages dans votre module:

 var myApp = angular.module('myApp', ['ngMessages']); 

ng-model-options dans AngularJS 1.3 (version bêta à la date d’écriture) est documenté pour prendre en charge {updateOn: ‘blur’}. Pour les versions antérieures, quelque chose comme les suivantes fonctionnait pour moi:

 myApp.directive('myForm', function() { return { require: 'form', link: function(scope, element, attrs, formController) { scope.validate = function(name) { formController[name].isInvalid = formController[name].$invalid; }; } }; }); 

Avec un modèle comme celui-ci:

 
Please enter a valid e-mail address.

Utilisez le champ $ touched Le champ a été touché pour cela, comme indiqué dans l’exemple ci-dessous.

 
You must enter a value

Vous pouvez définir dynamicment la classe css has-error (en supposant que vous utilisez bootstrap) en utilisant ng-class et une propriété sur la scope du contrôleur associé:

plunkr: http://plnkr.co/edit/HYDlaTNThZE02VqXrUCH?p=info

HTML:

 

Manette:

 $scope.badEmailAddress = false; $scope.emailBlurred = function (isValid) { $scope.badEmailAddress = !isValid; }; 

Si vous utilisez bootstrap 3 et lesscss, vous pouvez activer la validation sur le flou avec l’extrait suivant:

 :focus ~ .form-control-feedback.glyphicon-ok { display:none; } :focus ~ .form-control-feedback.glyphicon-remove { display:none; } .has-feedback > :focus { & { .form-control-focus(); } } 

outI a utilisé une directive. Voici le code:

 app.directive('onBlurVal', function () { return { ressortingct: 'A', link: function (scope, element, attrs, controller) { element.on('focus', function () { element.next().removeClass('has-visited'); element.next().addClass('has-focus'); }); element.on('blur', function () { element.next().removeClass('has-focus'); element.next().addClass('has-visited'); }); } } }) 

Tout mon contrôle d’entrée comporte un élément span comme élément suivant, c’est-à-dire l’endroit où mon message de validation est affiché et la directive en tant qu’atsortingbut est ajoutée à chaque contrôle d’entrée.

J’ai également (facultatif) .has-focus et la classe css visitée dans mon fichier css que vous voyez référencé dans la directive.

REMARQUE: n’oubliez pas d’append «on-blur-val» exactement de cette façon à votre contrôle d’entrée sans les apostrophes

En utilisant ng-focus, vous pouvez atteindre votre objective. vous devez fournir ng-focus dans votre champ de saisie. Et pendant que vous écrivez vos dérivés de ng-show, vous devez écrire une logique différente. Comme le code ci-dessous:

Nous pouvons utiliser des fonctions onfocus et onblur. Serait simple et meilleur

  
Name:
E-mail:

Essayez ici:

http://plnkr.co/edit/NKCmyru3knQiShFZ96tp?p=preview