我们在使用Angularjs进行开发时,已经提供了非常完备的表单验证框架,可以帮助我们很好的进行表单的校验工作,可是有时候因为一些业务逻辑的问题,会产生一些特殊的验证问题,这个时候我们就需要在angularjs中使用自定义验证了。
就比如我们这里的一个简单问题:从下面两张图中可以简单看到,在表单中有个邮件服务器配置的选项,如果启用,则必须填写展开的数据项。所以也就是说,关于邮件服务器配置项数据的校验是根据是否启用来做的。
实现方案
如果按照以前的开发方式,这种校验逻辑就是小毛毛雨,因为所有的表单验证都是自己写的,一串if-elseif-else就可以很好的实现出来。这样写没错,还能更好的理解表单验证的逻辑,适合学习的时候这样写,可是在实际项目开发过程中
这样写就有点反人类了,N多个字段,N多种校验,排查维护起来也是不小的工作。
使用验证框架,验证框架何其多,使用验证框架可以帮助我们很好的简单快捷完成表单验证,由于主要是介绍angularjs,所以就使用angularjs的验证框架来完成这种验证规则,当邮件服务器配置不启用的时候,则不会去验证邮件的配置项,如果启用了,则需要验证。
后续的内容需要有了解或使用过angularjs表单验证功能的基础,如果不是很了解,建议选查看一下angularjs是如何使用表单验证的,或者可以参考:
分析的过程就不多说了,直接上代码,大家可以在实践的过程中来理解。由于个人知识有限,也许angularjs已经提供过相关的验证方式,只是我没有了解到,如果有朋友知道,还请留言告知,谢过!
html代码段 - 一个简单的表单1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| <form name="youname_form" novalidate> <div class="form_item"> <label class="form_label ">其他必填设置:</label> <div class="form_input"> <input type="text" name="other_val" ng-model="configData.otherVal" required> </div> <div class="form_message"> <span class="success" ng-show="youname_form.other_val.$dirty && youname_form.other_val.$valid"><i class="tongtech tbcl-duihao">成功</i></span> <span class="error" ng-show="youname_form.other_val.$dirty && youname_form.other_val.$error.required">请填写其他设置</span> </div> </div> <div class="form_item"> <label class="form_label ">邮件配置:</label> <div class="form_input"> <input type="checkbox" ng-model="configData.mailServer.enable"> </div> <div class="form_message"> <span class="prompt"></span> </div> </div> <div ng-show="configData.mailServer.enable"> <div class="form_item"> <label class="form_label ">STMP服务地址:</label> <div class="form_input"> <input type="text" name="mailServer_smtp" ng-model="configData.mailServer.smtp" > </div> <div class="form_message"> <span class="success" ng-show="youname_form.mailServer_smtp.$dirty && youname_form.mailServer_smtp.$valid"><i class="tongtech tbcl-duihao">成功</i></span> <span class="error" ng-show="youname_form.mailServer_smtp.$dirty && youname_form.mailServer_smtp.$error.required">请填写STMP服务地址</span> </div> </div> </div> <div class="form_item"> <button ng-click="saveConfig(youname_form.$valid)">保存配置</button> <span>表单验证状态:{{youname_form.$valid}}</span> </div> </form>
|
js代码段 - 使用angularjs1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| var testModule = angular.module("tmodule", []); testModule.controller("testCtrl", function($scope) { $scope.configData = { otherVal:'', mailServer:{ enable: false, smtp: '' } }; var editVali = function(item) { item.$dirty = true; item.$pristine = false; } $scope.saveConfig = function(state) { if(!state) { editVali($scope.youname_form.other_val); if($scope.configData.mailServer.enable) { editVali($scope.youname_form.mailServer_smtp); } return; } alert('验证成功!'); } });
|
从上图不难看出,有个很明显的错误,当邮件配置启用的时候,STMP的验证是通过的。这是因为我们在html代码段第25行并没有添加**required(必填)**属性,导致该项为非必填项。
如果给添加上**required(必填)**属性呢?我们可以想一下(也可以自己试一下),如果添加上,那么表示该项为必填项,无论邮件配置是否启用,这里都会进行非空校验,所以也是不可取的。
所以说,单纯的**required(必填)校验并不能满足我们的需求,我们需要对required(必填)**校验进行扩展,来让这个非空的校验是有条件的判断。
接下来使用angularjs的自定义校验来扩展required(必填),我们命名为required-for,指定一个作为判断条件的属性,根据指定的属性来进行有条件的非空校验。注意:扩展的自定义验证,需要使用高版本的angularjs,只测试了一个1.2.6不支持扩展,1.4.6支持扩展。
js代码段 - 扩展required校验1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| testModule.directive('requiredFor',function(){ return { restrict: 'A', require: 'ngModel', link: function(scope, ele, attrs, ctrl){ if (!ctrl) return; var paramVal = null; scope.$watch(attrs.requiredFor, function(n){ paramVal = n; ctrl.$validate(); }); ctrl.$validators.required = function(modelValue, viewValue) { return !paramVal || !ctrl.$isEmpty(viewValue); }; ctrl.$parsers.push(function(viewValue){ if(paramVal){ if(ctrl.$isEmpty(viewValue)){ ctrl.$setValidity('required', false); }else{ ctrl.$setValidity('required', true); } }else{ ctrl.$setValidity('required', true); } return viewValue; }); } }; });
|
然后我们在html代码段第25行添加我们新的校验指令required-for=””
html代码段 - 添加新的校验指令1
| <input type="text" name="mailServer_smtp" ng-model="configData.mailServer.smtp" required-for="configData.mailServer.enable">
|
通过上图我们可以看到,表单的验证状态将会根据邮件配置的是否启用和STMP项是否填值来进行变化。
示例代码:https://github.com/yecaocode/angularjs-base/blob/master/L005.html
参考资料
- 整理后补