国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > JavaScript > 正文

Angular 輸入框實現自定義驗證功能

2019-11-19 17:30:44
字體:
來源:轉載
供稿:網友

此插件使用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);      }     }    });   }  } }]);

  通過 監聽 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]+)$/   }  } } ]) ;

       通過獲取輸入框 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');   }  } });

   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];  }) };

   整個代碼如下:

<!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8"> <title></title> <script src="jquery-1.11.1.js"></script> <script src="angular.js"></script> <style type="text/css">  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;  } </style></head><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><script type="text/javascript"> 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];  }) }; 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');   }  } }); 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]+)$/   }  } } ]) ; 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);      }     }    });   }  } }]);</script></html>

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 浪卡子县| 东海县| 维西| 邓州市| 丰宁| 米林县| 汾西县| 万载县| 息烽县| 汤原县| 井研县| 香港 | 青神县| 杂多县| 太康县| 平乐县| 建水县| 保山市| 乐业县| 修水县| 丹巴县| 分宜县| 库尔勒市| 常德市| 济源市| 大庆市| 明光市| 平昌县| 手游| 宾阳县| 东兰县| 玉田县| 新巴尔虎左旗| 伊春市| 甘德县| 镇江市| 通山县| 军事| 宁化县| 湘潭市| 万宁市|