show validation error messages on submit in angularjs

前端 未结 13 794
别那么骄傲
别那么骄傲 2020-11-28 02:25

I have a form which need to show validation error messages if clicked submit.

Here is a working plunker

 
相关标签:
13条回答
  • 2020-11-28 02:36

    There are two simple & elegant ways to do it.

    Pure CSS:

    After first form submission, despite the form validity, Angular will add a ng-submitted class to all form elements inside the form just submitted.

    We can use .ng-submitted to controller our element via CSS.

    if you want to display an error text only when user have submitted e.g.

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

    Using a value from Scope:
    After first form submission, despite the form validity, Angular will set [your form name].$submitted to true. Thus, we can use that value to control elements.

    <div ng-show="yourFormName.$submitted">error message</div>
    <form name="yourFormName"></form>
    
    0 讨论(0)
  • 2020-11-28 02:38

    Since I'm using Bootstrap 3, I use a directive: (see 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);
    

    and then in my 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>
    

    UPDATED

    In my latest project, I use Ionic so I have the following, which automatically puts .valid or .invalid on the input-item's:

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

    and then in the 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>
    

    and in the controller:

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

    so, now, in the CSS, you can do stuff like:

    .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;
    */
    }
    

    MUCH SIMPLER!

    0 讨论(0)
  • 2020-11-28 02:38

    You only need to check if the form is dirty and valid before submitting it. Checkout the following code.

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

    And also you can disable your submit button with the following change:

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

    This should help for your initial

    0 讨论(0)
  • 2020-11-28 02:39

    My solution with 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>
    
    0 讨论(0)
  • 2020-11-28 02:39
    // 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
    }
    
    0 讨论(0)
  • 2020-11-28 02:40

    I found this fiddle http://jsfiddle.net/thomporter/ANxmv/2/ which does a nifty trick to cause control validation.

    Basically it declares a scope member submitted and sets it true when you click submit. The model error binding use this extra expression to show the error message like

    submitted && form.email.$error.required
    

    UPDATE

    As pointed out in @Hafez's comment (give him some upvotes!), the Angular 1.3+ solution is simply:

    form.$submitted && form.email.$error.required
    
    0 讨论(0)
提交回复
热议问题