2

我有以下验证器指令:

directive('myValidate', function($timeout) {
    return {
        require: 'ngModel',
        link: function(scope, elm, attrs, ctrl) {
              if(!scope.requirementSpec){
                scope.requirementSpec = {}; 
              }
              if(Boolean(attrs.valueRequired) || Boolean(attrs.minLength) && elm[0].value != ""){
                console.log(scope.model[attrs.name]);
                ctrl.$setValidity(attrs.name, false);
                // elm.removeClass('ng-valid').addClass('ng-invalid');
                }


              elm.on('focus', function(){
                console.log(elm);
                console.log(ctrl);
                var form = elm.parents().find('form');
                // $timeout(function(){$ctrl.$dirty = true;}, 0);
              });
            ctrl.$parsers[0] = (function(viewValue) {

              scope.valid = true;
              scope.fieldName = attrs.name;
              var nameStr = attrs.name + '';
              var nameObj = nameStr.split('_');
              for(var i = 0; i < nameObj.length; ++i){
                nameObj[i] = nameObj[i].substr(0, 1).toUpperCase() + nameObj[i].slice(1);
              }
              var nameStrParsed = nameObj.join(' ');
              scope.fieldErrorDisplay = Boolean(nameStrParsed) ? nameStrParsed : 'This field';
              if(attrs.valueRequired && viewValue.length == 0 && !attrs.minLength){
                  scope.valid = false;  
                  scope.requirementSpec[nameStr] = [{
                    'msg' : scope.fieldErrorDisplay + ' is required',
                    'class' : undefined
                  }];
                }
                else{
                      // scope.fieldErrorDisplayObj[nameStr] = scope.fieldErrorDisplay + ' must meet the following requirements: ';
                      scope.requirementSpec[nameStr] = [];
                      if(attrs.minLength){
                        var itemValidity = viewValue.length >= attrs.minLength;
                        scope.valid = !itemValidity ? false : scope.valid;
                        var item = {
                          'msg' : 'At Least ' + attrs.minLength + ' Chars',
                          'class' : itemValidity ? 'valid' : undefined
                        };
                        scope.requirementSpecrequirementSpec[nameStr].push(item);
                      }
                      else if(attrs.valueRequired){
                        var itemValidity = viewValue && viewValue.length >= 1;
                        scope.valid = !itemValidity ? false : scope.valid;
                        var item = {
                          'msg' : 'This field must be filled',
                          'class' : itemValidity ? 'valid' : undefined
                        };
                        scope.requirementSpec[nameStr].push(item);
                      }
                      if(attrs.maxLength){
                        var itemValidity = viewValue.length <= attrs.maxLength;
                        scope.valid = !itemValidity ? false : scope.valid;
                        var item = {
                          'msg' :  attrs.maxLength + ' Chars At Most  ',
                          'class' : itemValidity ? 'valid' : undefined
                        };
                        scope.requirementSpec[nameStr].push(item);
                      }
                      if(attrs.minLetters){
                        var itemValidity = (viewValue && /[A-z]/.test(viewValue));
                        scope.valid = !itemValidity ? false : scope.valid;
                        var item = {
                          'msg' : 'Must contain at least ' + attrs.minLetters + ' letters',
                          'class' : itemValidity ? 'valid' : undefined
                        };
                        scope.requirementSpec[nameStr].push(item);
                      }
                      if(attrs.minNumbers){focus
                        var itemValidity = (viewValue && /\d/.test(viewValue));
                        scope.valid = !itemValidity ? false : scope.valid;
                        var item = {
                          'msg' : 'Must contain at least' + attrs.minNumbers + ' numbers',
                          'class' : itemValidity ? 'valid' : undefined
                        };
                        scope.requirementSpec[nameStr].push(item);
                      }
                }

                if(scope.valid) {
                  var errorsPresent = false;
                  for(var i = 0; i < scope.requirementSpec[nameStr].length; i++){
                    if(!scope.requirementSpec[nameStr][i].class){
                      errorsPresent = true;
                    }
                  }
                  scope.requirementSpec[nameStr] =  errorsPresent ? scope.requirementSpec[nameStr] : [];
                    ctrl.$setValidity(nameStr, true);
                    elm.removeClass('ng-required-invalid').removeClass('validatorError').removeClass('ng-invalid').addClass('ng-valid');
                    return viewValue;
                } else {
                    ctrl.$setValidity(nameStr, false);                    
                    return undefined;
                }

            });
        }
     };

}).

如您所见,在链接函数中,我检查了我应用此指令的输入元素的值是否为空,并将此元素的有效性设置为 false。

当我使用此指令验证编辑表单时,问题就出现了,其中值是通过对 REST 资源的 XHR 请求检索的。

我的问题是:我该如何处理这个问题,并将这个逻辑绑定到该字段的 ng-model 上,而不是 $watching 每个单独的,这将是一种可怕的浪费。

也许我可以让 $parser 对字段模型的变化做出反应,而不仅仅是直接用户输入?

4

2 回答 2

1

如果我理解正确,您是在尝试监听对 ngModel/Form 元素所做的更改?

尝试在您的 ngModel 上添加一个 $watch 侦听器,如下所示:

scope.$watch(attrs.ngModel, function(val) {
    // React the the value changes
})
于 2014-01-01T23:28:12.207 回答
0

答案在于表单的 Angularjs 文档: http ://docs.angularjs.org/api/ng.directive:ngModel.NgModelController# $formatters

$formatters 是模型与指令评估的值之间的管道。

请关闭。

于 2013-10-08T14:12:34.103 回答