English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Angular Input Box Custom Validation Function Implementation

This plugin is implemented using angular.js and JQuery. (The introduction of JQuery needs to be before angular.)

  Users can verify required items, integer type, floating-point type verification after entering data in the input box.

  If input box verification is inside the form, you can implement required item verification after clicking the submit button.

Effect as follows:

(1)Background red and other styles are marked when verification fails  

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

  because when the built-in verification of angular.js fails, it will automatically add .ng to the tag-invalid style, because this style is rewritten here

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

  (2)HTML code as follows

<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)This plugin uses directive myValid to implement

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 &63; 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 &63; 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) &63; value : undefined;
     validFn(ctrl.$modelValue, oldRules);
    });
    scope.$watch(attrs.ngModel, function (newVal, oldVal) {
     if (newVal === oldVal) {
      return;
     });
     if (ctrl.$modelValue != undefined && (ctrl.$invalid || el.hasClass('ng')) {-invalid))) {
      validFn(ctrl.$modelValue);
     });
    validFn(ctrl.$modelValue, oldRules);
    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);
   });
  });
 });

  The response to the change of the input box content is realized by listening to attrs.ngModel, verification rules rules, and ctrl.$parser.

  Once this directive is used, an ID is dynamically added to the current input box, so that after verification passes, the verification background information of the input box can be changed. 

(4)Verification logic processing 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 it is not a required item and there is no input value, clear the prompt box
    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) {
      //If it is a required item and has a value, return true
      flag = !isBlank;
     } else if (rule.contains(':')) {
      //If the validation rule is fn:ctrl.certCheck
      flag = this.checkRule(val, rule.split(', '));/:/), $scope, extendParam);
     else {
      //Validate rules are int, use regular expressions to match numbers, email, length
      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;
      });
     });
     //This is for what
     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]);//Specify the name of the function to be called certCheck
     var fn = $parse(fnName)($scope);
     if (!fn) {
      return true;
     });
     return fn.call($scope, val, extendParam);
    else {
     return true;
    });
   },
   checkValidForm: function (formName) {
    //Only check required items
    //Use attribute selector to get all elements inside
    var formContext = $('form[name="{0}"],[ng-form="{0}"],[data-ng-form="{0}"]'.format(formName)),
      validList = formContext.find('[my-valid]');//validList is not an array, it is a pseudo-array
    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 can be written directly on the interface.
    if (tips && tips.contains(':')) {
     return tips;
    });
    var msg = this.msgs[rule];
    if (msg) {
     63; tips.split(/:/)[0] : '';
     var params1 = '';
     
      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': 'required',
    'int': '{0} must be an integer'
   });
   ,
   pats: {
    'int': /^[\-\+]?([0-9]+)$/
   });
  });
 });
 ])
 ;

       Verification rules are obtained by getting the input box ele.myValid

   1and if it is required, then return the red marking for this input box, and when the mouse is moved over, the verification information "required" is displayed.

   2and if it is integer, floating-point type, etc., then verify through regular expression.

      3and if it is max (max) or min (min), then custom logic.

  4and if it is fn verification, then verify according to the corresponding function in the controller.

  5and if the submit button is clicked by the user, then judge whether the item is required, and if verification fails, the background of the corresponding element is marked red.

(5)Verification fails, prompt Factory---uiTipsFactory

app.factory('uiTipsFactory', function () {
  return {
   filterClass: function (ele, invalid) {
    if (invalid) {
     //If the verification does not pass
     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'
      validFn(ctrl.$modelValue, oldRules);
     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();
     validFn(ctrl.$modelValue, oldRules);
    });
    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');
   });
  });
 validFn(ctrl.$modelValue, oldRules);

   1and if verification fails, add background color, and CSS processing for the element as follows

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

   CSS processing as follows after verification passes  

 ele.removeClass('ng-invalid').addClass('ng-valid');

 

2and the background prompt is added as a div layer on the body.

(6)other related code

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

   The entire code is as follows:

<!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) {
     //If the verification does not pass
     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'
      validFn(ctrl.$modelValue, oldRules);
     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();
     validFn(ctrl.$modelValue, oldRules);
    });
    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');
   });
  });
 validFn(ctrl.$modelValue, oldRules);
 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 it is not a required item and there is no input value, clear the prompt box
    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) {
      //If it is a required item and has a value, return true
      flag = !isBlank;
     } else if (rule.contains(':')) {
      //If the validation rule is fn:ctrl.certCheck
      flag = this.checkRule(val, rule.split(', '));/:/), $scope, extendParam);
     else {
      //Validate rules are int, use regular expressions to match numbers, email, length
      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;
      });
     });
     //This is for what
     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]);//Specify the name of the function to be called certCheck
     var fn = $parse(fnName)($scope);
     if (!fn) {
      return true;
     });
     return fn.call($scope, val, extendParam);
    else {
     return true;
    });
   },
   checkValidForm: function (formName) {
    //Only check required items
    //Use attribute selector to get all elements inside
    var formContext = $('form[name="{0}"],[ng-form="{0}"],[data-ng-form="{0}"]'.format(formName)),
      validList = formContext.find('[my-valid]');//validList is not an array, it is a pseudo-array
    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 can be written directly on the interface.
    if (tips && tips.contains(':')) {
     return tips;
    });
    var msg = this.msgs[rule];
    if (msg) {
     63; tips.split(/:/)[0] : '';
     var params1 = '';
     
      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': 'required',
    'int': '{0} must be an integer'
   });
   ,
   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 &63; 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 &63; 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) &63; value : undefined;
     validFn(ctrl.$modelValue, oldRules);
    });
    scope.$watch(attrs.ngModel, function (newVal, oldVal) {
     if (newVal === oldVal) {
      return;
     });
     if (ctrl.$modelValue != undefined && (ctrl.$invalid || el.hasClass('ng')) {-invalid))) {
      validFn(ctrl.$modelValue);
     });
    validFn(ctrl.$modelValue, oldRules);
    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>

Declaration: The content of this article is from the Internet, and the copyright belongs to the original author. The content is contributed and uploaded by Internet users spontaneously. This website does not own the copyright, has not been edited by humans, and does not assume any relevant legal liability. If you find any content suspected of copyright infringement, please send an email to notice#w3Please report any violations by sending an email to codebox.com (replace # with @ when sending an email), and provide relevant evidence. Once verified, this site will immediately delete the infringing content.

You May Also Like