前言html
以前分享的《web项目演化--验证体系》中提到基于angular的验证,可是为了以防读者迷惑,可以好的理解验证体系,因此没有详细介绍。前端
今天特意补写一篇关于构建angular的验证。web
前端验证组件虽然对于美工的要求会更多,可是真实的应用环境下,其实对业务的要求会更高,须要组件有统一的规范,除非设计通用组件,不然应该更关注业务来进行设计。ajax
有了统一的验证组件,复合组件能够重用单一的文本框、输入框、复选框等组件,开发人员能够节省很多时间,而且在后期须要对网站风格统一调整的时候,只须要改变相应的组件便可完成变动。app
实现异步
首先须要定义一个验证的规则,须要包含验证的方式、验证参数,好比:['stringLength', { min: 1, max: 6 }],这是我当前使用的验证体系的规则,因为anuglar的便利性,咱们能够直接使用一个属性来存储该值。网站
有了规则,就须要一个验证的类来验证以上定义的规则,大体代码以下:ui
demo.factory('$validator', [ function () { return { stringLength: function (opts, value, callback) { if (typeof value !== 'string' && value != null) value = value.toString(); var min = opts.min || 0; var max = opts.max || 0; callback(value ? (max == 0 ? value.length >= min : value.length >= min && value.length <= max) : min === 0); } }; } ]);
验证方法中之因此使用异步回掉方式,是为ajax验证方式预留的。this
有了验证类,只要在组件中进行相应的引用,而后获取存有验证规则的属性,并用验证类进行验证便可,代码以下:spa
demo.directive('ucInput', [ '$validator', function ($validator) { return { replace: true, scope: { data: '=' }, template: '<input ng-style="{ \'background-color\': isValid && \'white\' || \'red\' }" type="text" ng-model="data" />', link: function (scope, el, attrs) { scope.isValid = true; var validType = scope.$parent.$eval(attrs.validType); el.bind('blur', function () { var fn = function () { scope.isValid = $validator[validType[0]](validType[1], scope.data); }; var phase = scope.$root.$$phase; if (phase == '$apply' || phase == '$digest') { if (fn && (typeof (fn) === 'function')) fn(); } else { scope.$apply(fn); } }); } }; } ]);
组件的效果比较丑,别在乎细节(^_^),当用户焦点离开组件的时候,组件就会进行验证,所以该组件就须要用户的主动操做才能有效果了。
然而若是用户不操做组件,直接点击提交按钮那该怎么办呢?
因而乎就须要一个容器指令,来包裹全部的验证组件,并在触发提交按钮的时候,也可让包含在内的全部验证组件本身触发验证。
咱们不可能在每个验证组件中都写一堆类似的验证代码来实现验证,并且业务中,若是组件移除或者隐藏都应该将组件排除到验证列表外,所以就须要一个额外的类来承担这个责任,代码以下:
demo.directive('ucForm', [ function () { return { require: 'ucForm', controller: [ function () { this.controls = []; } ], link: function (scope, _, attrs, formCtrl) { scope.onSubmit = function (callback) { var ep = new EventProxy(); ep.after('valid', formCtrl.controls.length, function (res) { var b = true; for (var i = 0; i < res.length; i++) { b = res[i]; if (!b) break; } if (b) callback(); }); for (var i = 0; i < formCtrl.controls.length; i++) { formCtrl.controls[i].valid(function (b) { ep.emit('valid', b); }); } }; } }; } ]); demo.factory('$valid-ui', [ '$validator', function ($validator) { function Control(validType, property) { this.validType = validType; this.disable = false; this.isValid = true; this.property = property; this.value = ''; } Control.prototype.valid = function (callback) { this.isValid = true; if (this.disable && callback) return callback(true); var self = this; $validator[this.validType[0]](this.validType[1], self.value, function (b) { if (callback) callback(b); self.isValid = b; }); }; return { create: function (validType, property) { return new Control(validType, property); } }; } ]);
有了以上的支持,接下来只须要修改一个ucInput,而且将ucForm.onSubmit绑定到提交按钮上即可以实现一键验证的效果了,具体的实现代码这里就不提供了。
结束语
那么基于angular的验证到这里就基本实现了,其余的扩展,例如:点击提交按钮的时候能够跳转到第一个错误组件的地方,只须要组件中经过获取组件坐标并滚动到相应的位置便可实现。
至于美观方面,就得看美工了,文章就到这里了,若是有错误或者问题的话,请你们留言,谢谢。