在angularjs中提交时显示验证错误消息


71

我有一个表格,如果单击“提交”,则需要显示验证错误消息。

这是一个工作的家伙

 <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>

用户开始进行更改时,验证工作正常。但是它不会显示任何错误消息。如果单击“提交”而不输入任何内容。

有实现这个的想法吗?或者以其他方式如何在单击“提交”按钮时使每个输入字段$ dirty


Answers:


104

我发现了这个小提琴http://jsfiddle.net/thomporter/ANxmv/2/上,它巧妙地进行了控件验证。

基本上,它声明一个作用域成员,submitted并在单击“提交”时将其设置为true。模型错误绑定使用此额外的表达式来显示错误消息,例如

submitted && form.email.$error.required

更新

正如@Hafez的评论中所指出(给他一些投票!),Angular 1.3+解决方案很简单:

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

57
只需form.$submitted根据文档docs.angularjs.org/guide/…使用
Hafez Divandari

2
是的,在Angular 1.3之后,此解决方案并不适用。现在有一个$提交的属性。
Chandermani 2015年

1
@Chandermani只是想说,请在我们工作的朋克中加入novalidate。:)
艾哈迈德·哈姆扎

@Chandermani:您能帮我这个链接吗?stackoverflow.com/questions/29557554/…–
rish

该解决方案有效,但我认为对于正常的用例而言,它不能满足要求,对于form.email。$ touched && form.email。$ error.required,错误也应显示出来,因此是实现该问题的最佳方法结果是将验证留给控制器方法,检查表单验证,然后为每个属性调用$ setTouched。
Badr slaoui

12

由于我使用的是Bootstrap 3,因此我使用了一条指令:(请参阅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);

然后在我的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>

更新

在我的最新项目中,我使用Ionic,因此具有以下内容,这些内容会自动放在.valid.invalidinput-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();
          }
        })
      ;

    }
  };
}])

然后在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>

并在控制器中:

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

    Authentication.emailLogin(data)
    //...

因此,现在,在CSS中,您可以执行以下操作:

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

更简单!


2
非常好!我对此做了一些改进,并在此jsfiddl中
Benny Bottema 2014年

稍加修改以要求表单控制器。现在,您仅可以在a上组合有效的Submit指令,<form>而不必再从范围中手动获取控制器。更新了jsfiddle
Benny Bottema 2014年

还有一个更新,现在包括自动专注于第一个输入(和一些注释):new jsfiddle
Benny Bottema 2014年

4
最好在这里放一个最终版本:final jsfiddle
Benny Bottema 2014年

1
@Plantface我将您的指令与另一个指令组合在一起,该指令循环遍历所有表单组div并监视输入,以便在验证状态更改时可以设置其has-error类。gist.github.com/anonymous/97efc4f2f12ba51c5cf3
BenCr,2015年

5

我也遇到了同样的问题,我通过添加ng-submit解决了这个问题,该提交将变量提交设置为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>

我喜欢使用$ submitted的想法,我想我必须将Angular升级到1.3;)


3

我可以提出两种方法来实现它。

第一个是删除 novalidate以启用浏览器的验证。

其次,您可以save在表单无效时禁用按钮,如下所示

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

希望能帮助到你。


谢谢,删除novalidate会给Safari iOS浏览器带来麻烦。它不提供验证弹出窗口。如果最初禁用“提交”按钮,对我(用户)来说也有点模棱两可。但这是处理它的好方法。
Gihan 2013年

3

有两种简单而优雅的方法可以做到这一点。

纯CSS:

首次提交表单后,尽管表单有效,但Angular会向ng-submitted刚提交的表单内的所有表单元素添加一个类。

我们可以用 .ng-submittedCSS来控制我们的元素。

如果您只想在用户提交后显示错误文本,例如

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

使用Scope中的值:
首次提交表单后,尽管表单有效,但Angular将设置[your form name].$submitted为true。因此,我们可以使用该值来控制元素。

<div ng-show="yourFormName.$submitted">error message</div>
<form name="yourFormName"></form>

是的,您现在可以在1.3+版本中执行此操作,但是当OP要求1.3尚未正式发布时:P
Squazz 2015年

2

我的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>

1
对jsfiddle ng-show =“(提交的&& form.last_name。$ invalid)||(!form.last_name。$ pristine && form.last_name。$ invalid)”的更改将使您能够:1.在表单加载,2.提交表单时显示所有无效的验证,3.触摸字段时显示验证消息。
chrisghardwick 2014年

@chrisghardwick能否请您更新您的建议?
Mo.

2

您只需要在提交表单之前检查表单是否脏了和有效。签出以下代码。

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

您还可以通过以下更改禁用“提交”按钮:

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

这应该对您的初始有帮助


2
您也可以使用frmRegister。$ pristine代替!frmRegister。$ dirty
csharpsql 2015年

1

http://jsfiddle.net/LRD5x/30/ 一个简单的解决方案。

的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

我喜欢realcrowd的解决方案的。

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

0
// 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

G45,

我遇到了同样的问题,我创建了一个指令,请检查以下内容,希望它会有所帮助

指令:

    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>

0

使用angularjs验证表单的完整解决方案。

HTML如下。

<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应用程序和控制器如下

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

重要代码段

  1. ng-app =“ areaApp” ng-controller =“ addCtrler”
    定义角度应用和控制器

  2. ng-show =“(fareainfo。$ submitted || fareainfo.name。$ dirty)&& fareainfo.name。$ error.required”
    以上条件确保用户每次看到表格时,屏幕上及之后均不存在任何验证错误。用户对表单进行更改,以确保在屏幕上显示验证消息。。名称。是输入元素的名称属性。

  3. $ scope.fareainfo。$ valid
    上面的代码,每当用户提交表单时,分段检查表单是否有效。

  4. $ scope.fareainfo。$ setSubmitted();
    在代码上方,segment确保了每当用户提交表单而未执行任何操作时,所有验证消息都会显示在屏幕上。


-3

试试这个代码:

<INPUT TYPE="submit" VALUE="Save" onClick="validateTester()">

此功能将验证您的结果

function validateTester() {
    var flag = true
    var Tester = document.forms.Tester
    if (Tester.line1.value!="JavaScript") {
        alert("First box must say 'JavaScript'!")
        flag = false
        }
    if (Tester.line2.value!="Kit") {
        alert("Second box must say 'Kit'!")
        flag = false
        }
    if (flag) {
        alert("Form is valid! Submitting form...")
        document.forms.Tester.submit()
        }
    }

对不起,我没有得到你的答案。什么是Tester对象?AngularJS中有东西吗?而且我不想弹出警报。只想显示隐藏的错误消息。谢谢您的回答
Gihan 2013年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.