项目演化系列--验证体系(基于angular的前端验证)

前言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的验证到这里就基本实现了,其余的扩展,例如:点击提交按钮的时候能够跳转到第一个错误组件的地方,只须要组件中经过获取组件坐标并滚动到相应的位置便可实现。

  至于美观方面,就得看美工了,文章就到这里了,若是有错误或者问题的话,请你们留言,谢谢。

相关文章
相关标签/搜索