Angular Form提交中所有字段的触发验证

时间:2013-06-05 12:29:12

标签: forms angularjs

我正在使用此方法:http://plnkr.co/edit/A6gvyoXbBd2kfToPmiiA?p=preview仅验证模糊字段。这工作正常,但我还想验证它们(并因此显示那些字段的错误,如果有的话)当用户点击“提交”按钮(不是真正的提交但是对数据的数据点击调用)

点击该按钮有没有办法在所有字段上再次触发验证?

13 个答案:

答案 0 :(得分:42)

我知道,回答有点太晚了,但你需要做的就是强迫所有表格变脏。请看下面的代码:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 22
    buildToolsVersion '22.0.1'

    defaultConfig {
        applicationId "br.liveo.ndrawer"
        minSdkVersion 21
        targetSdkVersion 22
        versionCode 1
        versionName "1.0"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_7
        targetCompatibility JavaVersion.VERSION_1_7
    }
}

dependencies {
    compile project(':library')
    compile fileTree(include: ['*.jar'], dir: 'libs')
    compile 'com.android.support:design:22.2.0'
    compile 'com.android.support:appcompat-v7:22.2.0'
}

然后您可以使用以下方式检查表单是否有效

angular.forEach($scope.myForm.$error.required, function(field) {
    field.$setDirty();
});

最后,我想,如果一切看起来都不错,你会想改变你的路线:

if($scope.myForm.$valid) {
    //Do something
}   

编辑:在触发提交事件之前,表单不会在范围内注册。只需使用ng-submit指令来调用一个函数,并将上面的函数包装在该函数中,它应该可以工作。

答案 1 :(得分:41)

对我有用的是使用$setSubmitted函数,该函数首先出现在1.3.20版本的角度文档中。

在我想触发验证的点击事件中,我执行了以下操作:

vm.triggerSubmit = function() {
    vm.homeForm.$setSubmitted();
    ...
}

这就是我所需要的一切。根据文档,它“将表单设置为其提交的状态”。它被提到here

答案 2 :(得分:14)

如果有人稍后再回来......以上都不适合我。因此,我深入研究了角度形式验证的内容,并找到了他们调用的函数来执行给定字段上的验证器。此属性称为$validate

如果您有一个命名表单myForm,则可以通过编程方式调用myForm.my_field.$validate()来执行字段验证。例如:

<div ng-form name="myForm">
    <input required name="my_field" type="text" ng-blur="myForm.my_field.$validate()">
</div>

请注意,调用$validate会对您的模型产生影响。来自ngModelCtrl的角度文档。$ validate:

  

运行每个已注册的验证器(第一个同步验证器,然后运行异步验证器)。如果有效性更改为无效,则模型将设置为undefined,除非ngModelOptions.allowInvalid为true。如果有效性更改为有效,则会将模型设置为最后一个可用的有效$ modelValue,即最后一个已解析的值或从范围设置的最后一个值。

因此,如果您计划使用无效的模型值(例如弹出消息告诉他们),那么您需要确保将allowInvalid设置为true模型。

答案 3 :(得分:12)

您可以使用 Angular-Validator 来执行您想要的操作。这很简单易用。

会:

  • 仅验证$dirtysubmit
  • 上的字段
  • 如果表单无效,则阻止提交表单
  • 字段为$dirty或表单已提交
  • 后显示自定义错误消息

<强> See the demo

示例

<form angular-validator 
       angular-validator-submit="myFunction(myBeautifulForm)"
       name="myBeautifulForm">
       <!-- form fields here -->
    <button type="submit">Submit</button>
</form>

如果字段未通过validator,则用户将无法提交表单。

查看angular-validator use cases and examples了解详情。

免责声明:我是Angular-Validator的作者

答案 4 :(得分:11)

嗯,角度方式是让它处理验证, - 因为它在每次模型更改时都会执行 - 并且只在需要时向用户显示结果。

在这种情况下,您决定何时显示错误,您只需设置一个标志: http://plnkr.co/edit/0NNCpQKhbLTYMZaxMQ9l?p=preview

据我所知,有一个问题归结为角度让我们有更高级的表单控制。由于没有解决,我会使用它而不是重新发明所有现有的验证方法。

编辑:但是如果你坚持自己的方式,那么在提交之前,这是你修改过的小提琴。 http://plnkr.co/edit/Xfr7X6JXPhY9lFL3hnOw?p=preview 控制器在单击按钮时广播事件,指令执行验证魔术。

答案 5 :(得分:9)

一种方法是强制所有属性都是脏的。你可以在每个控制器中执行此操作,但它会变得非常混乱。最好有一个通用的解决方案。

我能想到的最简单的方法是使用指令

  • 它将处理表单提交属性
  • 它遍历所有表单字段并将原始字段标记为脏
  • 在调用提交函数之前检查表单是否有效

这是指令

myModule.directive('submit', function() {
  return {
    restrict: 'A',
    link: function(scope, formElement, attrs) {
      var form;
      form = scope[attrs.name];
      return formElement.bind('submit', function() {
        angular.forEach(form, function(field, name) {
          if (typeof name === 'string' && !name.match('^[\$]')) {
            if (field.$pristine) {
              return field.$setViewValue(field.$value);
            }
          }
        });
        if (form.$valid) {
          return scope.$apply(attrs.submit);
        }
      });
    }
  };
});

并更新您的表单html,例如:

 <form ng-submit='justDoIt()'>

变为:

 <form name='myForm' novalidate submit='justDoIt()'>

请在此处查看完整示例:http://plunker.co/edit/QVbisEK2WEbORTAWL7Gu?p=preview

答案 6 :(得分:3)

这是我显示表单错误消息的全局函数。

 function show_validation_erros(form_error_object) {
        angular.forEach(form_error_object, function (objArrayFields, errorName) {
            angular.forEach(objArrayFields, function (objArrayField, key) {
                objArrayField.$setDirty();
            });
        });
    };

在我的任何控制器中,

if ($scope.form_add_sale.$invalid) { 
    $scope.global.show_validation_erros($scope.form_add_sale.$error);
}

答案 7 :(得分:2)

根据Thilak的回答,我能够提出这个解决方案......

由于我的表单字段仅显示验证消息,如果某个字段无效且已被用户触摸,我可以使用此按钮触发的代码来显示我的无效字段:

&#13;
&#13;
// Show/trigger any validation errors for this step
angular.forEach(vm.rfiForm.stepTwo.$error, function(error) {
  angular.forEach(error, function(field) {
    field.$setTouched();
  });
});
// Prevent user from going to next step if current step is invalid
if (!vm.rfiForm.stepTwo.$valid) {
  isValid = false;
}
&#13;
<!-- form field -->
<div class="form-group" ng-class="{ 'has-error': rfi.rfiForm.stepTwo.Parent_Suffix__c.$touched && rfi.rfiForm.stepTwo.Parent_Suffix__c.$invalid }">

  <!-- field label -->
  <label class="control-label">Suffix</label>
  <!-- end field label -->
  <!-- field input -->
  <select name="Parent_Suffix__c" class="form-control"
          ng-options="item.value as item.label for item in rfi.contact.Parent_Suffixes"
          ng-model="rfi.contact.Parent_Suffix__c" />
  <!-- end field input -->
  <!-- field help -->
  <span class="help-block" ng-messages="rfi.rfiForm.stepTwo.Parent_Suffix__c.$error" ng-show="rfi.rfiForm.stepTwo.Parent_Suffix__c.$touched">
    <span ng-message="required">this field is required</span>
  </span>  
  <!-- end field help -->
</div>
<!-- end form field -->
&#13;
&#13;
&#13;

答案 8 :(得分:2)

注意:我知道这是一个hack,但它对Angular 1.2及更早版本没有提供简单的机制很有用。

验证启动了更改事件,因此以编程方式更改值等一些操作不会触发它。但触发更改事件将触发验证。例如,使用jQuery:

$('#formField1, #formField2').trigger('change');

答案 9 :(得分:1)

要在我想要的时候验证表单的所有字段,我会对$$控件的每个字段进行验证,如下所示:

angular.forEach($scope.myform.$$controls, function (field) {
    field.$validate();
});

答案 10 :(得分:0)

我喜欢this approach处理按钮点击验证。

  1. 无需从控制器调用任何内容,

  2. 全部用指令处理。

  3. on github

答案 11 :(得分:0)

你可以试试这个:

&#13;
&#13;
// The controller

$scope.submitForm = function(form){
   		//Force the field validation
   		angular.forEach(form, function(obj){
   			if(angular.isObject(obj) && angular.isDefined(obj.$setDirty))
   			{ 
   				obj.$setDirty();
   			}
   		})
        
        if (form.$valid){
		
			$scope.myResource.$save(function(data){
		     	//....
			});
		}
}
&#13;
<!-- FORM -->

  <form name="myForm"  role="form" novalidate="novalidate">
<!-- FORM GROUP to field 1 -->
  <div class="form-group" ng-class="{ 'has-error' : myForm.field1.$invalid && myForm.field1.$dirty }">
      <label for="field1">My field 1</label>
        <span class="nullable"> 
        <select name="field1" ng-model="myresource.field1" ng-options="list.id as list.name for list in listofall"
          class="form-control input-sm" required>
            <option value="">Select One</option>
        </select>
        </span>
        <div ng-if="myForm.field1.$dirty" ng-messages="myForm.field1.$error" ng-messages-include="mymessages"></div>
  </div>
    
<!-- FORM GROUP to field 2 -->
  <div class="form-group" ng-class="{ 'has-error' : myForm.field2.$invalid && myForm.field2.$dirty }">
    <label class="control-label labelsmall" for="field2">field2</label> 
      <input name="field2" min="1" placeholder="" ng-model="myresource.field2" type="number" 
      class="form-control input-sm" required>
    <div ng-if="myForm.field2.$dirty" ng-messages="myForm.field2.$error" ng-messages-include="mymessages"></div>
  </div>

  </form>

<!-- ... -->
<button type="submit" ng-click="submitForm(myForm)">Send</button>
&#13;
&#13;
&#13;

答案 12 :(得分:0)

我做了以下工作以使其发挥作用。

<form name="form" name="plantRegistrationForm">
  <div ng-class="{ 'has-error': (form.$submitted || form.headerName.$touched) && form.headerName.$invalid }">
    <div class="col-md-3">
      <div class="label-color">HEADER NAME 
        <span class="red"><strong>*</strong></span></div>
    </div>
    <div class="col-md-9">
      <input type="text" name="headerName" id="headerName" 
             ng-model="header.headerName" 
             maxlength="100" 
             class="form-control" required>
      <div ng-show="form.$submitted || form.headerName.$touched">
        <span ng-show="form.headerName.$invalid" 
              class="label-color validation-message">Header Name is required</span>
      </div>
    </div>
  </div>

  <button ng-click="addHeader(form, header)" 
          type="button" 
          class="btn btn-default pull-right">Add Header
  </button>

</form>

在您的控制器中,您可以这样做;

addHeader(form, header){
        let self = this;
        form.$submitted = true;
        ... 
    }

你也需要一些CSS;

.label-color {
            color: $gray-color;
        }
.has-error {
       .label-color {
            color: rgb(221, 25, 29);
        }
        .select2-choice.ui-select-match.select2-default {
            border-color: #e84e40;
        }
    }
.validation-message {
       font-size: 0.875em;
    }
    .max-width {
        width: 100%;
        min-width: 100%;
    }