码迷,mamicode.com
首页 > 其他好文 > 详细

angular 输入框实现自定义验证

时间:2017-02-19 00:16:58      阅读:1120      评论:0      收藏:0      [点我收藏+]

标签:return   last   idf   ini   extend   bre   attr   最大   pad   

此插件使用angular.js、JQuery实现。(jQuery的引入需在angular 之前)

  用户可以 在输入框输入数据后验证 必填项、整数型、浮点型验证。

  如果在form 里面的输入框验证,可以点击 提交按钮后,实现 必填项验证。

效果图如下:

  技术分享

 

(1)验证未通过时,背景标红等样式为  

技术分享
 input.ng-invalid, select.ng-invalid {
            background-color: #ee82ee !important;
            border: 1px solid #CCC;
        }

        .qtip {
            position: absolute;
            max-width: 260px;
            display: none;
            min-width: 50px;
            font-size: 10.5px;
            line-height: 12px;
            direction: ltr;
        }

        .qtip-content {
            position: relative;
            padding: 5px 9px;
            overflow: hidden;
            text-align: left;
            word-wrap: break-word;
        }

        .qtip-rounded, .qtip-tipsy {
            -moz-border-radius: 5px;
            -webkit-border-radius: 5px;
            border-radius: 5px;
        }

        .qtipmodal-ie6fix {
            position: absolute !important;
        }

        .box-shadow-tips {
            background-color: #F63;
            border-color: #F5A88F;
            color: white;
            -moz-box-shadow: 2px 2px 2px #969696;
            -webkit-box-shaow: 2px 2px 2px #969696;
            box-shadow: 2px 2px 2px #969696;
        }
背景标红等样式

  因为angular.js 内置验证未通过时,会自动为 标签 增加 .ng-invalid 样式,因为这里重写此样式

  input.ng-invalid, select.ng-invalid {
  background-color: #ee82ee !important;
  border: 1px solid #CCC;
  } 
(2)HTML 代码如下
<body ng-app="myApp">
<form name="baseInfoForm">
    <div ng-controller="testCtrl">
        <input type="text" ng-model="age" my-valid="r"><br>
        <input type="text" ng-model="name" my-valid="int fn:certCheck"><br>
        <input type="button" value="提交" ng-click="submit()">
    </div>
</form>
</body>

 

(3)此插件使用 directive myValid 实现

技术分享
app.directive(‘myValid‘, [‘$parse‘, ‘uiTipsFactory‘, ‘uiValidFactory‘, function ($parse, tips, valid) {
        var uiValidAttrIdName = ‘ui-valid-id‘;
        return {
            restrict: ‘A‘,
            require: ‘ngModel‘,
            link: function (scope, el, attrs, ctrl) {
                var validId = el.attr(uiValidAttrIdName);

                if (!validId) {
                    validId = Math.guid();
                    el.attr(uiValidAttrIdName, validId);
                }

                var getRules = function () {
                    return attrs.myValid;
                };

                var lastOldRules;

                var validFn = function (value, oldRules) {
                    var sp = ‘_‘;
                    var rules = getRules();
                    var r = valid.check(value, rules, scope, attrs.uiValidTips);
                    if (lastOldRules && !oldRules) {
                        oldRules = lastOldRules;
                    }

                    if (r.flag && oldRules) {
                        rules = rules ? rules + ‘ ‘ + oldRules : oldRules;
                    }

                    if (rules) {
                        var arrInner = rules.split(‘ ‘);
                        var i = 0;
                        for (; i < arrInner.length; i++) {
                            var oneRule = arrInner[i];
                            if (!oneRule.trim()) {
                                continue;
                            }

                            ctrl.$setValidity(attrs.ngModel + sp + oneRule, r.flag ? true : oneRule != r.rule);
                        }
                    }

                    if (!r.flag) {
                        tips.on(el, r.msg);
                    } else {
                        tips.off(el);
                    }

                    return r.flag;
                };

                var init = function () {
                    var rules = getRules();
                    if (!rules) {
                        return;
                    }

                    var parsers = ctrl.$parsers;
                    if (parsers && parsers.length > 0) {
                        parsers.clean();
                    }

                    parsers.unshift(function (value) {
                        return validFn(value) ? value : undefined;
                    });
                };

                scope.$watch(attrs.ngModel, function (newVal, oldVal) {
                    if (newVal === oldVal) {
                        return;
                    }
                    if (ctrl.$modelValue != undefined && (ctrl.$invalid || el.hasClass(‘ng-invalid‘))) {
                        validFn(ctrl.$modelValue);
                    }
                });

                scope.$watch(getRules, function (newRules, oldRules) {
                    init();

                    lastOldRules = oldRules;

                    if (ctrl.$modelValue === undefined || ctrl.$modelValue === null) {
                        var needValid = false;
                        el.hasClass(‘ng-invalid‘);
                        var isValNaN = ctrl.$viewValue !== ctrl.$viewValue;

                        if (ctrl.$invalid || (ctrl.$viewValue !== undefined && !isValNaN)) {
                            needValid = true;
                        }


                        if (needValid) {
                            ctrl.$setViewValue(ctrl.$viewValue);
                        }

                    } else {
                        if (!ctrl.$dirty && attrs.dirtyCheck) {
                            console.log(‘----‘);
                        } else {
                            validFn(ctrl.$modelValue, oldRules);
                        }
                    }
                });


            }
        }
    }]);
directive--myValid

  通过 监听 attrs.ngModel,验证规则 rules ,ctrl.$parser 来实现 输入框内容改变的响应。

  一旦使用此directive,则动态为当前输入框添加ID,以便在 验证通过后,改变输入框的验证背景信息。

 

(4)验证逻辑处理 uiValidFactory

技术分享
app.factory(‘uiValidFactory‘, [‘$parse‘, ‘uiTipsFactory‘, function ($parse, tips) {
        return {
            check: function (val, rules, $scope, defaultTips, extendParam) {
                if (!rules) {
                    return {
                        flag: true
                    };
                }

                var rulesArr = rules.split(‘ ‘),
                        isBlank = val === null || val === undefined || val === ‘‘ || (‘‘ + val === ‘‘);

                //如果不是必填项 且没有输入值 则清除提示框
                if ($.inArray(‘r‘, rulesArr) === -1 && isBlank) {
                    return {
                        flag: true
                    }
                }
                var i = 0, len = rulesArr.length;
                for (; i < len; i++) {
                    var rule = rulesArr[i];
                    if (!rule) {
                        continue;
                    }

                    var flag = true;
                    if (‘r‘ === rule) {
                        //如果是必填项,有值 返回true
                        flag = !isBlank;
                    } else if (rule.contains(‘:‘)) {
                        //如果校验规则是 fn:ctrl.certCheck
                        flag = this.checkRule(val, rule.split(/:/), $scope, extendParam);
                    } else {
                        //校验 规则是 int 用正则匹配 数字 邮箱 长度
                        var pat = this.pats[rule];
                        if (pat instanceof RegExp) {
                            if (angular.isString(val)) {
                                flag = this.mat(val, pat);
                            }
                        } else if (angular.isFunction(pat)) {
                            flag = pat(val);
                        } else {
                            flag = false;
                        }
                    }

                    //这是干什么的呢
                    if (angular.isString(flag)) {
                        return {
                            flag: false,
                            msg: flag,
                            rule: rule
                        }
                    }

                    if (flag === false) {
                        var msg = this.getMsg(rule, defaultTips) || this.getMsg(‘tips.valid‘);
                        console.log(msg);
                        return {
                            flag: false,
                            msg: msg,
                            rule: rule
                        }
                    }
                }

                return {
                    flag: true
                }
            },
            checkRule: function (val, ruleArr, $scope, extendParam) {
                //ruleArr fn:certCheck
                var rule = ruleArr[0];
                if (rule === ‘fn‘) {
                    fnName = ruleArr[1];//指定被调函数的名字 certCheck
                    var fn = $parse(fnName)($scope);
                    if (!fn) {
                        return true;
                    }
                    return fn.call($scope, val, extendParam);
                } else {
                    return true;
                }
            },
            checkValidForm: function (formName) {
                //只检查必填项
                //使用属性筛选器 获得里面所有的元素
                var formContext = $(‘form[name="{0}"],[ng-form="{0}"],[data-ng-form="{0}"]‘.format(formName)),
                        validList = formContext.find(‘[my-valid]‘);//validList 不是数组,是伪数组
                if (!validList.length) {
                    return;
                }

                var that = this,
                        validFlags = [];
                validList.each(function () {
                            var ele = $(this),
                                    val = ele.val(),
                                    ruleStr = ele.attr(‘my-valid‘);
                            if (!ruleStr) {
                                return true;
                            }
                            if (angular.isString(val)) {
                                val = val.trim();
                            }

                            var validRules = ruleStr.split(‘ ‘);
                            if ($.inArray(‘r‘, validRules) != -1 && !val) {
                                var modelValue = ele.attr(‘ng-model‘) || ele.attr(‘data-ng-model‘);
                                validFlags.push(modelValue);
                                tips.on(ele, that.getMsg(‘r‘));
                            }
                        }
                );
                return validFlags;
            },
            mat: function (val, pat) {
                if (!pat) {
                    return;
                }
                return pat.test(val);
            }

            ,
            getMsg: function (rule, tips) {
                tips = tips || ‘‘;
                //可以在界面上直接写 tips
                if (tips && tips.contains(‘:‘)) {
                    return tips;
                }

                var msg = this.msgs[rule];
                if (msg) {
                    var params0 = tips.contains(‘:‘) ? tips.split(/:/)[0] : ‘‘;
                    var params1 = ‘‘;
                    if (rule.startsWith(‘min‘) || rule.startsWith(‘max‘)) {
                        var ruleArr = rule.split(/:/);
                        params1 = ruleArr[ruleArr.length - 1];
                    }
                    return msg.format(params0, params1);
                } else {

                }
            }
            ,
            regPat: function (code, pat, msg) {
                if (this.pat[code]) {
                    return;
                }

                this.pats[code] = pat;
                this.msgs[code] = msg;

            }
            ,
            msgs: {
                ‘r‘: ‘必填‘,
                ‘int‘: ‘{0}必须为整数‘
            }
            ,
            pats: {
                ‘int‘: /^[\-\+]?([0-9]+)$/
            }
        }
    }
    ])
    ;
uiValidFactory

       通过获取输入框 ele.myValid  验证规则,

   1、如果是必填,则返回 标红此输入框,鼠标移上,则显示 验证信息 “必填””。

   2、如果是整数、浮点型等验证,则通过 正则表达式进行验证。

      3、如果是最大(max)、最小(min),则自定义逻辑。

  4、如果是 fn 验证,则根据 对应controller中函数进行验证。

  5、用户点击提交按钮,则 判断是否必填项,验证不通过,对应元素背景标红。

 

(5) 验证不通过,提示Factory---uiTipsFactory

技术分享
app.factory(‘uiTipsFactory‘, function () {
        return {
            filterClass: function (ele, invalid) {
                if (invalid) {
                    //如果验证不通过
                    ele.removeClass(‘ng-valid‘).removeClass(‘ng-pristine‘).addClass(‘ng-invalid‘).addClass(‘ng-dirty‘);
                } else {
                    ele.removeClass(‘ng-invalid‘).addClass(‘ng-valid‘);
                }
            },
            on: function (ele, msg) {
                var lastTip = ele.data(‘last-tip‘);
                if (lastTip && lastTip === msg) {
                    return;
                }

                ele.data(‘last-tip‘, msg);
                this.filterClass(ele, true);

                var offset = ele.offset();
                if (!offset.top && !offset.left && ele.is(‘hidden‘)) {
                    offset = ele.show().offset();
                }

                var id = ele.attr(‘ui-valid-id‘);
                if (!id) {
                    id = Math.guid();
                    ele.attr(‘ui-valid-id‘, id);
                }

                if (id.contains(‘.‘)) {
                    id = id.replace(/\./g, ‘_‘);
                }

                var top = offset.top,
                        left = offset.left;

                var getTips = function () {
                    var _tip = $(‘#vtip_‘ + id);
                    if (_tip.length) {
                        _tip.html(msg).css({
                            ‘display‘: ‘none‘,
                            ‘top‘: top + ‘px‘,
                            ‘left‘: left + ele.width() + 10 + ‘px‘
                        });

                    } else {
                        var html = ‘<div id="vtip_‘ + id + ‘" class="vtip qtip  qtip-rounded box-shadow-tips">‘ +
                                ‘<div class="qtip-content">‘ + msg + ‘</div>‘;
                        $(html).css({
                            ‘display‘: ‘none‘,
                            ‘position‘: ‘absolute‘,
                            ‘top‘: top + ‘px‘,
                            ‘left‘: left + ele.width() + 10 + ‘px‘
                        }).appendTo($(‘body‘));
                    }
                };

                var bindTipsShow = function () {
                    getTips();
                    ele.unbind(‘mouseenter mouseleave‘).bind(‘mouseenter‘, function () {
                        var _tip = $(‘#vtip_‘ + id);
                        if (_tip.is(‘:hidden‘)) {
                            _tip.show();
                        }
                    }).bind(‘mouseleave‘, function () {
                        $(‘#vtip_‘ + id).hide();
                    });

                };

                bindTipsShow();
            },
            off: function (ele) {
                ele.data(‘last-tip‘, ‘‘);
                this.filterClass(ele);
                var id = ele.attr(‘ui-valid-id‘);

                if (!id) {
                    return;
                }

                if (id.contains(‘.‘)) {
                    id = id.replace(/\./g, ‘_‘);
                }

                $(‘#vtip_‘ + id).remove();
                ele.unbind(‘mouseenter mouseleave‘);
            }
        }
    });
uiTipsFactory

   1、验证不通过,增加背景色,元素css处理如下

      ele.removeClass(‘ng-valid‘).removeClass(‘ng-pristine‘).addClass(‘ng-invalid‘).addClass(‘ng-dirty‘);

   验证通过,CSS处理如下
    
ele.removeClass(‘ng-invalid‘).addClass(‘ng-valid‘);
  2、背景提示语,则是在body上增加一个div层。

(6)其他相关代码
技术分享
 var app = angular.module(‘myApp‘, []);

    app.controller(‘testCtrl‘, [‘$scope‘, ‘uiValidFactory‘, function ($scope, uiValidFactory) {
                $scope.certCheck = function (val) {
                    if (val > 32) {
                        return "数字太大了";
                    }
                    return true;
                };

                $scope.submit = function () {
                    if (!uiValidFactory.checkValidForm($scope.baseInfoForm.$name)) {

                    }

                };
            }]
    );

    Math.guid = function () {
        var a = "", b = 1;
        for (; b <= 32; b++) {
            var c = Math.floor(Math.random() * 16).toString(16);
            a += c;
            if (b === 8 || b === 12 || b === 16 || b === 20) {
                a += ‘-‘;
            }
        }
        return a;
    };

    String.prototype.contains = String.prototype.contains || function (a) {
        return this.indexOf(a) != -1;
    };

    String.prototype.format = String.prototype.format || function () {
        var a = Array.prototype.slice.call(arguments);
        return this.replace(/\{(\d+)}/g, function (c, b) {
            return a[b];
        })
    };
others

   整个代码如下:

技术分享
  1 <!DOCTYPE html>
  2 <html>
  3 <head lang="en">
  4     <meta charset="UTF-8">
  5     <title></title>
  6     <script src="jquery-1.11.1.js"></script>
  7     <script src="angular.js"></script>
  8     <style type="text/css">
  9 
 10         input.ng-invalid, select.ng-invalid {
 11             background-color: #ee82ee !important;
 12             border: 1px solid #CCC;
 13         }
 14 
 15         .qtip {
 16             position: absolute;
 17             max-width: 260px;
 18             display: none;
 19             min-width: 50px;
 20             font-size: 10.5px;
 21             line-height: 12px;
 22             direction: ltr;
 23         }
 24 
 25         .qtip-content {
 26             position: relative;
 27             padding: 5px 9px;
 28             overflow: hidden;
 29             text-align: left;
 30             word-wrap: break-word;
 31         }
 32 
 33         .qtip-rounded, .qtip-tipsy {
 34             -moz-border-radius: 5px;
 35             -webkit-border-radius: 5px;
 36             border-radius: 5px;
 37         }
 38 
 39         .qtipmodal-ie6fix {
 40             position: absolute !important;
 41         }
 42 
 43         .box-shadow-tips {
 44             background-color: #F63;
 45             border-color: #F5A88F;
 46             color: white;
 47             -moz-box-shadow: 2px 2px 2px #969696;
 48             -webkit-box-shaow: 2px 2px 2px #969696;
 49             box-shadow: 2px 2px 2px #969696;
 50         }
 51     </style>
 52 </head>
 53 <body ng-app="myApp">
 54 <form name="baseInfoForm">
 55     <div ng-controller="testCtrl">
 56         <input type="text" ng-model="age" my-valid="r"><br>
 57         <input type="text" ng-model="name" my-valid="int fn:certCheck"><br>
 58         <input type="button" value="提交" ng-click="submit()">
 59     </div>
 60 </form>
 61 </body>
 62 <script type="text/javascript">
 63     var app = angular.module(‘myApp‘, []);
 64 
 65     app.controller(‘testCtrl‘, [‘$scope‘, ‘uiValidFactory‘, function ($scope, uiValidFactory) {
 66                 $scope.certCheck = function (val) {
 67                     if (val > 32) {
 68                         return "数字太大了";
 69                     }
 70                     return true;
 71                 };
 72 
 73                 $scope.submit = function () {
 74                     if (!uiValidFactory.checkValidForm($scope.baseInfoForm.$name)) {
 75 
 76                     }
 77 
 78                 };
 79             }]
 80     );
 81 
 82     Math.guid = function () {
 83         var a = "", b = 1;
 84         for (; b <= 32; b++) {
 85             var c = Math.floor(Math.random() * 16).toString(16);
 86             a += c;
 87             if (b === 8 || b === 12 || b === 16 || b === 20) {
 88                 a += ‘-‘;
 89             }
 90         }
 91         return a;
 92     };
 93 
 94     String.prototype.contains = String.prototype.contains || function (a) {
 95         return this.indexOf(a) != -1;
 96     };
 97 
 98     String.prototype.format = String.prototype.format || function () {
 99         var a = Array.prototype.slice.call(arguments);
100         return this.replace(/\{(\d+)}/g, function (c, b) {
101             return a[b];
102         })
103     };
104 
105     app.factory(‘uiTipsFactory‘, function () {
106         return {
107             filterClass: function (ele, invalid) {
108                 if (invalid) {
109                     //如果验证不通过
110                     ele.removeClass(‘ng-valid‘).removeClass(‘ng-pristine‘).addClass(‘ng-invalid‘).addClass(‘ng-dirty‘);
111                 } else {
112                     ele.removeClass(‘ng-invalid‘).addClass(‘ng-valid‘);
113                 }
114             },
115             on: function (ele, msg) {
116                 var lastTip = ele.data(‘last-tip‘);
117                 if (lastTip && lastTip === msg) {
118                     return;
119                 }
120 
121                 ele.data(‘last-tip‘, msg);
122                 this.filterClass(ele, true);
123 
124                 var offset = ele.offset();
125                 if (!offset.top && !offset.left && ele.is(‘hidden‘)) {
126                     offset = ele.show().offset();
127                 }
128 
129                 var id = ele.attr(‘ui-valid-id‘);
130                 if (!id) {
131                     id = Math.guid();
132                     ele.attr(‘ui-valid-id‘, id);
133                 }
134 
135                 if (id.contains(‘.‘)) {
136                     id = id.replace(/\./g, ‘_‘);
137                 }
138 
139                 var top = offset.top,
140                         left = offset.left;
141 
142                 var getTips = function () {
143                     var _tip = $(‘#vtip_‘ + id);
144                     if (_tip.length) {
145                         _tip.html(msg).css({
146                             ‘display‘: ‘none‘,
147                             ‘top‘: top + ‘px‘,
148                             ‘left‘: left + ele.width() + 10 + ‘px‘
149                         });
150 
151                     } else {
152                         var html = ‘<div id="vtip_‘ + id + ‘" class="vtip qtip  qtip-rounded box-shadow-tips">‘ +
153                                 ‘<div class="qtip-content">‘ + msg + ‘</div>‘;
154                         $(html).css({
155                             ‘display‘: ‘none‘,
156                             ‘position‘: ‘absolute‘,
157                             ‘top‘: top + ‘px‘,
158                             ‘left‘: left + ele.width() + 10 + ‘px‘
159                         }).appendTo($(‘body‘));
160                     }
161                 };
162 
163                 var bindTipsShow = function () {
164                     getTips();
165                     ele.unbind(‘mouseenter mouseleave‘).bind(‘mouseenter‘, function () {
166                         var _tip = $(‘#vtip_‘ + id);
167                         if (_tip.is(‘:hidden‘)) {
168                             _tip.show();
169                         }
170                     }).bind(‘mouseleave‘, function () {
171                         $(‘#vtip_‘ + id).hide();
172                     });
173 
174                 };
175 
176                 bindTipsShow();
177             },
178             off: function (ele) {
179                 ele.data(‘last-tip‘, ‘‘);
180                 this.filterClass(ele);
181                 var id = ele.attr(‘ui-valid-id‘);
182 
183                 if (!id) {
184                     return;
185                 }
186 
187                 if (id.contains(‘.‘)) {
188                     id = id.replace(/\./g, ‘_‘);
189                 }
190 
191                 $(‘#vtip_‘ + id).remove();
192                 ele.unbind(‘mouseenter mouseleave‘);
193             }
194         }
195     });
196 
197     app.factory(‘uiValidFactory‘, [‘$parse‘, ‘uiTipsFactory‘, function ($parse, tips) {
198         return {
199             check: function (val, rules, $scope, defaultTips, extendParam) {
200                 if (!rules) {
201                     return {
202                         flag: true
203                     };
204                 }
205 
206                 var rulesArr = rules.split(‘ ‘),
207                         isBlank = val === null || val === undefined || val === ‘‘ || (‘‘ + val === ‘‘);
208 
209                 //如果不是必填项 且没有输入值 则清除提示框
210                 if ($.inArray(‘r‘, rulesArr) === -1 && isBlank) {
211                     return {
212                         flag: true
213                     }
214                 }
215                 var i = 0, len = rulesArr.length;
216                 for (; i < len; i++) {
217                     var rule = rulesArr[i];
218                     if (!rule) {
219                         continue;
220                     }
221 
222                     var flag = true;
223                     if (‘r‘ === rule) {
224                         //如果是必填项,有值 返回true
225                         flag = !isBlank;
226                     } else if (rule.contains(‘:‘)) {
227                         //如果校验规则是 fn:ctrl.certCheck
228                         flag = this.checkRule(val, rule.split(/:/), $scope, extendParam);
229                     } else {
230                         //校验 规则是 int 用正则匹配 数字 邮箱 长度
231                         var pat = this.pats[rule];
232                         if (pat instanceof RegExp) {
233                             if (angular.isString(val)) {
234                                 flag = this.mat(val, pat);
235                             }
236                         } else if (angular.isFunction(pat)) {
237                             flag = pat(val);
238                         } else {
239                             flag = false;
240                         }
241                     }
242 
243                     //这是干什么的呢
244                     if (angular.isString(flag)) {
245                         return {
246                             flag: false,
247                             msg: flag,
248                             rule: rule
249                         }
250                     }
251 
252                     if (flag === false) {
253                         var msg = this.getMsg(rule, defaultTips) || this.getMsg(‘tips.valid‘);
254                         console.log(msg);
255                         return {
256                             flag: false,
257                             msg: msg,
258                             rule: rule
259                         }
260                     }
261                 }
262 
263                 return {
264                     flag: true
265                 }
266             },
267             checkRule: function (val, ruleArr, $scope, extendParam) {
268                 //ruleArr fn:certCheck
269                 var rule = ruleArr[0];
270                 if (rule === ‘fn‘) {
271                     fnName = ruleArr[1];//指定被调函数的名字 certCheck
272                     var fn = $parse(fnName)($scope);
273                     if (!fn) {
274                         return true;
275                     }
276                     return fn.call($scope, val, extendParam);
277                 } else {
278                     return true;
279                 }
280             },
281             checkValidForm: function (formName) {
282                 //只检查必填项
283                 //使用属性筛选器 获得里面所有的元素
284                 var formContext = $(‘form[name="{0}"],[ng-form="{0}"],[data-ng-form="{0}"]‘.format(formName)),
285                         validList = formContext.find(‘[my-valid]‘);//validList 不是数组,是伪数组
286                 if (!validList.length) {
287                     return;
288                 }
289 
290                 var that = this,
291                         validFlags = [];
292                 validList.each(function () {
293                             var ele = $(this),
294                                     val = ele.val(),
295                                     ruleStr = ele.attr(‘my-valid‘);
296                             if (!ruleStr) {
297                                 return true;
298                             }
299                             if (angular.isString(val)) {
300                                 val = val.trim();
301                             }
302 
303                             var validRules = ruleStr.split(‘ ‘);
304                             if ($.inArray(‘r‘, validRules) != -1 && !val) {
305                                 var modelValue = ele.attr(‘ng-model‘) || ele.attr(‘data-ng-model‘);
306                                 validFlags.push(modelValue);
307                                 tips.on(ele, that.getMsg(‘r‘));
308                             }
309                         }
310                 );
311                 return validFlags;
312             },
313             mat: function (val, pat) {
314                 if (!pat) {
315                     return;
316                 }
317                 return pat.test(val);
318             }
319 
320             ,
321             getMsg: function (rule, tips) {
322                 tips = tips || ‘‘;
323                 //可以在界面上直接写 tips
324                 if (tips && tips.contains(‘:‘)) {
325                     return tips;
326                 }
327 
328                 var msg = this.msgs[rule];
329                 if (msg) {
330                     var params0 = tips.contains(‘:‘) ? tips.split(/:/)[0] : ‘‘;
331                     var params1 = ‘‘;
332                     if (rule.startsWith(‘min‘) || rule.startsWith(‘max‘)) {
333                         var ruleArr = rule.split(/:/);
334                         params1 = ruleArr[ruleArr.length - 1];
335                     }
336                     return msg.format(params0, params1);
337                 } else {
338 
339                 }
340             }
341             ,
342             regPat: function (code, pat, msg) {
343                 if (this.pat[code]) {
344                     return;
345                 }
346 
347                 this.pats[code] = pat;
348                 this.msgs[code] = msg;
349 
350             }
351             ,
352             msgs: {
353                 ‘r‘: ‘必填‘,
354                 ‘int‘: ‘{0}必须为整数‘
355             }
356             ,
357             pats: {
358                 ‘int‘: /^[\-\+]?([0-9]+)$/
359             }
360         }
361     }
362     ])
363     ;
364 
365     app.directive(‘myValid‘, [‘$parse‘, ‘uiTipsFactory‘, ‘uiValidFactory‘, function ($parse, tips, valid) {
366         var uiValidAttrIdName = ‘ui-valid-id‘;
367         return {
368             restrict: ‘A‘,
369             require: ‘ngModel‘,
370             link: function (scope, el, attrs, ctrl) {
371                 var validId = el.attr(uiValidAttrIdName);
372 
373                 if (!validId) {
374                     validId = Math.guid();
375                     el.attr(uiValidAttrIdName, validId);
376                 }
377 
378                 var getRules = function () {
379                     return attrs.myValid;
380                 };
381 
382                 var lastOldRules;
383 
384                 var validFn = function (value, oldRules) {
385                     var sp = ‘_‘;
386                     var rules = getRules();
387                     var r = valid.check(value, rules, scope, attrs.uiValidTips);
388                     if (lastOldRules && !oldRules) {
389                         oldRules = lastOldRules;
390                     }
391 
392                     if (r.flag && oldRules) {
393                         rules = rules ? rules + ‘ ‘ + oldRules : oldRules;
394                     }
395 
396                     if (rules) {
397                         var arrInner = rules.split(‘ ‘);
398                         var i = 0;
399                         for (; i < arrInner.length; i++) {
400                             var oneRule = arrInner[i];
401                             if (!oneRule.trim()) {
402                                 continue;
403                             }
404 
405                             ctrl.$setValidity(attrs.ngModel + sp + oneRule, r.flag ? true : oneRule != r.rule);
406                         }
407                     }
408 
409                     if (!r.flag) {
410                         tips.on(el, r.msg);
411                     } else {
412                         tips.off(el);
413                     }
414 
415                     return r.flag;
416                 };
417 
418                 var init = function () {
419                     var rules = getRules();
420                     if (!rules) {
421                         return;
422                     }
423 
424                     var parsers = ctrl.$parsers;
425                     if (parsers && parsers.length > 0) {
426                         parsers.clean();
427                     }
428 
429                     parsers.unshift(function (value) {
430                         return validFn(value) ? value : undefined;
431                     });
432                 };
433 
434                 scope.$watch(attrs.ngModel, function (newVal, oldVal) {
435                     if (newVal === oldVal) {
436                         return;
437                     }
438                     if (ctrl.$modelValue != undefined && (ctrl.$invalid || el.hasClass(‘ng-invalid‘))) {
439                         validFn(ctrl.$modelValue);
440                     }
441                 });
442 
443                 scope.$watch(getRules, function (newRules, oldRules) {
444                     init();
445 
446                     lastOldRules = oldRules;
447 
448                     if (ctrl.$modelValue === undefined || ctrl.$modelValue === null) {
449                         var needValid = false;
450                         el.hasClass(‘ng-invalid‘);
451                         var isValNaN = ctrl.$viewValue !== ctrl.$viewValue;
452 
453                         if (ctrl.$invalid || (ctrl.$viewValue !== undefined && !isValNaN)) {
454                             needValid = true;
455                         }
456 
457 
458                         if (needValid) {
459                             ctrl.$setViewValue(ctrl.$viewValue);
460                         }
461 
462                     } else {
463                         if (!ctrl.$dirty && attrs.dirtyCheck) {
464                             console.log(‘----‘);
465                         } else {
466                             validFn(ctrl.$modelValue, oldRules);
467                         }
468                     }
469                 });
470 
471 
472             }
473         }
474     }]);
475 
476 </script>
477 </html>
all code

 

 

angular 输入框实现自定义验证

标签:return   last   idf   ini   extend   bre   attr   最大   pad   

原文地址:http://www.cnblogs.com/xianrongbin/p/6414417.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!