web-dev-qa-db-fra.com

affiche les messages d'erreur de validation sur submit dans angularjs

J'ai un formulaire qui doit afficher des messages d'erreur de validation si vous cliquez sur Soumettre.

Voici un travail plunker

 <form name="frmRegister" ng-submit="register();" novalidate>
      <div>
        <input placeholder="First Name" name="first_name" type="text" ng-model="user.firstName" required />
        <span ng-show="frmRegister.first_name.$dirty && frmRegister.first_name.$error.required">First Name is required</span>
      </div>
      <div>
        <input placeholder="Last Name" name="last_name" type="text" ng-model="user.lastName" required />
        <span ng-show="frmRegister.last_name.$dirty && frmRegister.last_name.$error.required">Last Name is required</span>
      </div>
      <div>
        <input placeholder="Email" name="email" type="email" ng-model="user.email" required />
        <span ng-show="frmRegister.email.$dirty && frmRegister.email.$error.required">Email is required.</span>
        <span ng-show="frmRegister.email.$dirty && frmRegister.email.$error.email">Invalid Email address.</span>
      </div>
      <input type="submit" value="Save" />
      <span ng-show="registered">YOU ARE NOW REGISTERED USER</span>
 </form>

La validation fonctionne normalement lorsque l'utilisateur commence à apporter des modifications. Mais il ne montre aucun message d'erreur Si vous cliquez dessus, soumettez sans rien entrer. 

Toute pensée de réaliser ceci?. Ou bien, comment rendre chaque champ de saisie $ sale lorsque vous cliquez sur le bouton Soumettre

68
Gihan

J'ai trouvé ce violon http://jsfiddle.net/thomporter/ANxmv/2/ qui fait une astuce astucieuse pour provoquer la validation du contrôle.

Fondamentalement, il déclare un membre de la portée submitted et le définit comme vrai lorsque vous cliquez sur soumettre. La liaison d'erreur de modèle utilise cette expression supplémentaire pour afficher le message d'erreur comme suit:

submitted && form.email.$error.required

METTRE &AGRAVE; JOUR

Comme indiqué dans commentaire de @ Hafez (donnez-lui quelques votes positifs!), Le solution angulaire 1.3+ est tout simplement:

form.$submitted && form.email.$error.required
101
Chandermani

Depuis que j'utilise Bootstrap 3, j’utilise une directive: (Voir plunkr )

    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() {
                                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);

puis dans mon HTML:

<form class="form-horizontal" role="form" name="form" novalidate valid-submit="connect()">
  <div class="form-group">
    <div class="input-group col col-sm-11 col-sm-offset-1">
      <span class="input-group-addon input-large"><i class="glyphicon glyphicon-envelope"></i></span>
      <input class="input-large form-control" type="email" id="email" placeholder="Email" name="email" ng-model="email" required="required">
    </div>
    <p class="col-sm-offset-3 help-block error" ng-show="form.$submitted && form.email.$error.required">please enter your email</p>
    <p class="col-sm-offset-3 help-block error" ng-show="form.$submitted && form.email.$error.email">please enter a valid email</p>
  </div>
</form>

MIS &AGRAVE; JOUR

Dans mon dernier projet, j'utilise Ionic. J'ai donc le texte suivant, qui met automatiquement .valid ou .invalid sur les input-item:

.directive('input', ['$timeout', function ($timeout) {
  function findParent(element, selector) {
    selector = selector || 'item';
    var parent = element.parent();
    while (parent && parent.length) {
      parent = angular.element(parent);
      if (parent.hasClass(selector)) {
        break;
      }
      parent = parent && parent.parent && parent.parent();
    }
    return parent;
  }

  return {
    restrict: 'E',
    require: ['?^ngModel', '^form'],
    priority: 1,
    link: function (scope, element, attrs, ctrls) {
      var ngModelCtrl = ctrls[0];
      var form = ctrls[1];

      if (!ngModelCtrl || form.$name !== 'form' || attrs.type === 'radio' || attrs.type === 'checkbox') {
        return;
      }

      function setValidClass() {
        var parent = findParent(element);
        if (parent && parent.toggleClass) {
          parent.addClass('validated');
          parent.toggleClass('valid', ngModelCtrl.$valid && (ngModelCtrl.$dirty || form.$submitted));
          parent.toggleClass('invalid', ngModelCtrl.$invalid && (ngModelCtrl.$dirty || form.$submitted));
          $timeout(angular.noop);
        }
      }

      scope.$watch(function () {
        return form.$submitted;
      }, function (b, a) {
        setValidClass();
      });


      var before = void 0;
      var update = function () {
        before = element.val().trim();
        ngModelCtrl.$setViewValue(before);
        ngModelCtrl.$render();
        setValidClass();
      };
      element
        .on('focus', function (e) {
          if (ngModelCtrl.$pristine) {
            element.removeClass('$blurred');
          }

        })
        .on('blur', function (e) {
          if (ngModelCtrl.$dirty) {
            setValidClass();
            element.addClass('$blurred');
          }
        }).on('change', function (e) {
          if (form.$submitted || element.hasClass('$blurred')) {
            setValidClass();
          }
        }).on('paste', function (e) {
          if (form.$submitted || element.hasClass('$blurred')) {
            setValidClass();
          }
        })
      ;

    }
  };
}])

puis dans le HTML:

    <form name='form' novalidate="novalidate" ng-submit="auth.signin(form, vm)">
          <label class="item item-input item-floating-label">
            <span class="input-label">Email</span>
            <input type="email" placeholder="Email" ng-model="vm.email" autofocus="true" required
              >
          </label>
          <button ng-if="!posting" type="submit" class="item button-block item-balanced item-icon-right  call-to-action">Login<i class="icon ion-chevron-right"></i>
          </button>

et dans le contrôleur:

  self.signin = function (form, data) {
    if (!form.$valid) return;

    Authentication.emailLogin(data)
    //...

donc, maintenant, dans le CSS, vous pouvez faire des choses comme:

.item.valid::before{
    float: right;
    font-family: "Ionicons";
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    text-rendering: auto;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    color: #66cc33;
    margin-right: 8px;
    font-size: 24px;
    content: "\f122";
}

.item.invalid::before{
    float: right;
    font-family: "Ionicons";
    font-style: normal;
    font-weight: normal;
    font-variant: normal;
    text-transform: none;
    text-rendering: auto;
    line-height: 1;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    color: #ef4e3a;
    margin-right: 8px;
    font-size: 24px;
    content: "\f12a";

/*
    border-left: solid 2px #ef4e3a !important;
    border-right: solid 2px #ef4e3a !important;
*/
}

BEAUCOUP PLUS SIMPLE!

12
malix

J'ai également eu le même problème, j'ai résolu le problème en ajoutant un ng-submit qui définit la variable soumise sur true.

<form name="form" ng-submit="submitted = true" novalidate>
<div>
    <span ng-if="submitted && form.email.$error.email">invalid email address</span> 
    <span ng-if="submitted && form.email.$error.required">required</span>
    <label>email</label>
    <input type="email" name="email" ng-model="user.email" required>
</div>

<div>
    <span ng-if="submitted && form.name.$error.required">required</span>
    <label>name</label>
    <input type="text" name="name" ng-model="user.name" required>
</div>

<button ng-click="form.$valid && save(user)">Save</button>
</form>

J'aime l'idée d'utiliser $ soumis, je pense avoir mis à jour Angular à 1.3;)

5
Georg Koller

Je peux trouver 2 façons de le réaliser.

La première consiste à supprimer novalidate pour activer la validation du navigateur.

Deuxièmement, vous pouvez désactiver le bouton save lorsque le formulaire n'est pas valide comme ceci

<input ng-disabled="!frmRegister.$valid" type="submit" value="Save" />

J'espère que ça aide.

3
zsong

Ma solution avec bootstrap 3

http://jsfiddle.net/rimian/epxrbzn9/

<form class="form" name="form" ng-app novalidate>
  <div class="form-group">
    <input name="first_name"
          type="text"
          class="form-control"
          ng-model="first_name"
          placeholder="First Name"
          required />
  </div>
  <div class="form-group">
    <input name="last_name"
          type="text"
          class="form-control"
          ng-model="last_name"
          placeholder="Last Name"
          required />
  </div>

  <button
    type="submit"
    class="btn btn-primary btn-large"
    ng-click="submitted=true">
      Submit
  </button>

<div ng-show="submitted && form.$invalid" class="alert alert-danger">
  <div ng-show="form.first_name.$error.required">
    First Name is Required
  </div>
  <div ng-show="form.last_name.$error.required">
    Last Name is Required
  </div>
</div>

</form>
2
Rimian

Tellement de réponses compliquées.

voici mon moyen simple.

En gros, il y a deux façons de résoudre votre problème.

Manière CSS:
Lorsque vous soumettez un formulaire, que votre formulaire soit valide ou non, Angular ajoute une classe ng-submitted à l'élément de formulaire . Nous pouvons utiliser .ng-submitted pour contrôler notre élément.
par exemple.

.error { display: none }
.ng-submitted .error {
     display: block;
}

Manière portée:
Lorsque vous soumettez un formulaire, que votre formulaire soit valide ou non, Angular définira [your form name].$submitted sur true.

<div ng-show="customizedFormName.$submitted">error message</div>
<form name="customizedFormName"></form>
2
Eric Chen

Vous devez seulement vérifier si le formulaire est sale et valide avant de le soumettre. Commander le code suivant.

<form name="frmRegister" data-ng-submit="frmRegister.$valid && frmRegister.$dirty ? register() : return false;" novalidate>      

Et vous pouvez également désactiver votre bouton d'envoi avec les modifications suivantes:

<input type="submit" value="Save" data-ng-disable="frmRegister.$invalid || !frmRegister.$dirty" />

Cela devrait aider pour votre première 

2
bekco

J'aime la solution de realcrowd the best.

HTML:

<form role="form" id="form" name="form" autocomplete="off" novalidate rc-submit="signup()">
<div class="form-group" ng-class="{'has-error':  rc.form.hasError(form.firstName)}">
    <label for="firstName">Your First Name</label>
    <input type="text" id="firstName" name="firstName" class="form-control input-sm" placeholder="First Name" ng-maxlength="40" required="required" ng-model="owner.name.first"/>
    <div class="help-block" ng-show="rc.form.hasError(form.firstName)">{{rc.form.getErrMsg(form.firstName)}}</div>
</div>
</form>

javascript:

//define custom submit directive
var rcSubmitDirective = {
'rcSubmit': ['$parse', function ($parse) {
    return {
        restrict: 'A',
        require: ['rcSubmit', '?form'],
        controller: ['$scope', function ($scope) {
            this.attempted = false;

            var formController = null;

            this.setAttempted = function() {
                this.attempted = true;
            };

            this.setFormController = function(controller) {
              formController = controller;
            };

            this.hasError = function (fieldModelController) {
                if (!formController) return false;

                if (fieldModelController) {
                    return fieldModelController.$invalid && this.attempted;
                } else {
                    return formController && formController.$invalid && this.attempted;
                }
            };
            this.getErrMsg=function(ctrl){
                var e=ctrl.$error;
                var errMsg;
                if (e.required){
                    errMsg='Please enter a value';
                }
                return errMsg;
            }
        }],
        compile: function(cElement, cAttributes, transclude) {
            return {
                pre: function(scope, formElement, attributes, controllers) {

                    var submitController = controllers[0];
                    var formController = (controllers.length > 1) ? controllers[1] : null;

                    submitController.setFormController(formController);

                    scope.rc = scope.rc || {};
                    scope.rc[attributes.name] = submitController;
                },
                post: function(scope, formElement, attributes, controllers) {

                    var submitController = controllers[0];
                    var formController = (controllers.length > 1) ? controllers[1] : null;
                    var fn = $parse(attributes.rcSubmit);

                    formElement.bind('submit', function (event) {
                        submitController.setAttempted();
                        if (!scope.$$phase) scope.$apply();

                        if (!formController.$valid) return false;

                        scope.$apply(function() {
                            fn(scope, {$event:event});
                        });
                    });
                }
          };
        }
    };
}]
};
app.directive(rcSubmitDirective);
1
Karthik Sankar

http://jsfiddle.net/LRD5x/30/ Une solution simple.

HTML

<form ng-submit="sendForm($event)" ng-class={submitted:submitted}>

JS

$scope.sendForm = function($event) {
  $event.preventDefault()
  $scope.submitted = true
};

CSS

.submitted input.ng-invalid:not(:focus) {
    background-color: #FA787E;
}

input.ng-invalid ~ .alert{
    display:none;
}
.submitted input.ng-invalid ~ .alert{
    display:block;
}
1
Frank Fang

Une solution complète à la forme de validation avec angularjs.

HTML est la suivante. 

<div ng-app="areaApp" ng-controller="addCtrler">
        <form class="form-horizontal" name="fareainfo">
            <div class="form-group">
                  <label for="input-areaname" class="col-sm-2 control-label">Area Name : </label>
                  <div class="col-sm-4">
                      <input type="text" class="form-control" name="name" id="input-areaname" ng-model="Area.Name" placeholder="" required>
                      <span class="text-danger" ng-show="(fareainfo.$submitted || fareainfo.name.$dirty) && fareainfo.name.$error.required"> Field is required</span>
                  </div>
            </div>
             <div class="col-sm-12">
                  <button type="button" class="btn btn-primary pull-right" ng-click="submitAreaInfo()">Submit</button>
             </div>
        </form>
    </div>

AngularJS App et le contrôleur est comme suit

var areaApp = angular.module('areaApp', []); 
areaApp.controller('addCtrler', function ($scope) {
    $scope.submitAreaInfo = function () {  
       if ($scope.fareainfo.$valid) {
         //after Form is Valid
       } else {
          $scope.fareainfo.$setSubmitted();
       }
    };
});

Segments de code importants

  1. ng-app = "areaApp" ng-controller = "addCtrler"
    Définit l'application angulaire et le contrôleur

  2. ng-show = "(fareainfo. $ submit || fareainfo.name. $ dirty) && fareainfo.name. $ error.required"  
    La condition ci-dessus garantit que, lorsqu'un utilisateur voit le formulaire pour la première fois, aucune erreur de validation ne s’affiche à l’écran et, une fois que celui-ci a été modifié, le message de validation est affiché. .prénom. est l'attribut name de l'élément input.

  3. $ scope.fareainfo. $ valid
    Au-dessus du code, segment vérifie si le formulaire est valide chaque fois qu'un utilisateur le soumet.

  4. $ scope.fareainfo. $ setSubmitted ();
    Au-dessus du code, segment garantit que tous les messages de validation sont affichés à l'écran chaque fois qu'un utilisateur soumet le formulaire sans rien faire.

0
shana
// This worked for me.
<form  name="myForm" class="css-form" novalidate ng-submit="Save(myForm.$invalid)">
<input type="text" name="uName" ng-model="User.Name" required/>
<span ng-show="User.submitted && myForm.uName.$error.required">Name is required.</span>
<input ng-click="User.submitted=true" ng-disabled="User.submitted && tForm.$invalid" type="submit" value="Save" />
</form>
// in controller
$scope.Save(invalid)
{
if(invalid) return;
// save form
}

G45,

J'ai fait face au même problème, j'ai créé une directive, veuillez cocher ci-dessous, espérons qu'elle peut être utile

Directive:

    app.directive('formSubmitValidation', function () {

        return {
            require: 'form',
            compile: function (tElem, tAttr) {

                tElem.data('augmented', true);

                return function (scope, elem, attr, form) {
                    elem.on('submit', function ($event) {
                        scope.$broadcast('form:submit', form);

                        if (!form.$valid) {
                            $event.preventDefault();
                        }
                        scope.$apply(function () {
                            scope.submitted = true;
                        });


                    });
                }
            }
        };


  })

HTML:

<form  name="loginForm" class="c-form-login" action="" method="POST" novalidate="novalidate" form-submit-validation="">

<div class="form-group">
                                                <input type="email" class="form-control c-square c-theme input-lg" placeholder="Email" ng-model="_username" name="_username" required>
                                                <span class="glyphicon glyphicon-user form-control-feedback c-font-grey"></span>
                                                <span ng-show="submitted || loginForm._username.$dirty && loginForm._username.$invalid">
                                                    <span ng-show="loginForm._username.$invalid" class="error">Please enter a valid email.</span>
                                                </span>
                                            </div>
<button type="submit" class="pull-right btn btn-lg c-theme-btn c-btn-square c-btn-uppercase c-btn-bold">Login</button>
</form>