AngularJS : Transclude a single input element into a directive template without using a container

标签 angularjs angularjs-directive angularjs-scope transclusion

我想为我的输入字段创建一个包装器,其中包含一个输入帮助工具提示。

我正在使用 angular 1.0.7,如果它很重要的话。

我正在使用 transclude: true 和隔离范围,以允许同时在几个不同的字段中出现错误,并且仍然保持对外部 $scope 的 ng-model 引用。

问题 :

当我在输入元素上使用此指令时,输入元素不会将 ('Transclude') 克隆到指令模板中。

因此,我在 DOM 中得到一个空的 div 元素,带有 ng-transclude 属性。

啪啪啪:
http://plnkr.co/edit/vFB9ih6x2NBmwhAes3Qh?p=preview

代码:

<input data-my-validate-input data-value-required="true" type="password" class="loginItem" placeholder="Password" name="password" data-ng-model="formData.password" data-display-name="Password">

但是,当我将此输入元素包装在 span 或 div 中时,子输入元素被超越得很好,但是我没有在指令中获得对正确外部 ng-model(ctrl) 的引用。
<span data-my-validate-input data-value-required="true" data-display-name="Password">
      <input type="password" class="loginItem" placeholder="Password" name="password" data-ng-model="formData.password" >    
</span>

完整代码(链接函数内部的逻辑与问题无关,但我更喜欢发布我的完整代码)
directive('myValidateInput', function() {
    return {
        require: 'ngModel',
          restrict: 'A',
          transclude: true,
          scope: {
            displayName: '@',
            valueRequired: '@',
            maxLength: '@',
            minLength: '@',
            minLetters: '@',
            minNumbers: '@'
          },
          template: '<div class="validationContainer">\
                      <div ng-transclude></div>\
                      <div class="input-help">\
                        <h4>{{fieldErrorDisplay}}</h4>\
                        <ul>\
                          <li data-ng-repeat="rule in requirementSpec" ng-class="rule.class">\
                              {{rule.msg}}\
                          </li>\
                        </ul>\
                      </div>\
                    </div>',
         replace: true,
         link: function(scope, elm, attrs, ctrl) {
                 var validator = function(viewValue){
                          if(scope.valueRequired && viewValue.length == 0 && (!scope.maxLength && !scope.minLength && !scope.minLetters && !scope.minNumbers)){
                    scope.valid = false;  
                    scope.fieldErrorDisplay = scope.fieldName + ' is required';
                  }
                  else{
                        scope.fieldErrorDisplay = scope.fieldName + ' must meet the following requirements: ';
                        scope.requirementSpec = [];
                        if(scope.minLength){
                          var itemValidity = viewValue.length >= scope.minLength;
                          scope.valid = !itemValidity ? false : scope.valid;
                          var item = {
                            'msg' : 'Must be at least ' + scope.minLength + ' characters long',
                            'class' : itemValidity ? 'valid' : undefined
                          };
                          scope.requirementSpec[nameStr].push(item);
                        }
                        else if(scope.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(scope.maxLength){
                          var itemValidity = viewValue.length <= scope.maxLength;
                          scope.valid = !itemValidity ? false : scope.valid;
                          var item = {
                            'msg' : 'Must be ' + scope.maxLength + ' characters long at most  ',
                            'class' : itemValidity ? 'valid' : undefined
                          };
                          scope.requirementSpec[nameStr].push(item);
                        }
                        if(scope.minLetters){
                          var itemValidity = (viewValue && /[A-z]/.test(viewValue));
                          scope.valid = !itemValidity ? false : scope.valid;
                          var item = {
                            'msg' : 'Must contain at least ' + scope.minLetters + ' letters',
                            'class' : itemValidity ? 'valid' : undefined
                          };
                          scope.requirementSpec[nameStr].push(item);
                        }
                        if(attrs.minNumbers){
                          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) {
                      ctrl.$setValidity(nameStr, true);
                      return viewValue;
                  } else {
                      ctrl.$setValidity(nameStr, false);                    
                      return undefined;
                  }
             }

             scope.requirementSpec = {};

             ctrl.$parsers.unshift(function(viewValue) {
               return validator(viewValue);
             });
             ctrl.$formatters.unshift(function(viewValue) {
               // var before = scope.$eval(attrs.validateBefore);
               if(viewValue && viewValue != "" && viewValue.length > 0)
                 return validator(viewValue);

             });


        });
    }
});

最佳答案

解决方案:
$transclude 只获取元素的编译内容,而不是它自己的元素。

显然,我在我的实现中缺乏对这个重要细节的理解。

关于AngularJS : Transclude a single input element into a directive template without using a container,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19220632/

相关文章:

angularjs - ionic 2 Highcharts 不可见

angularjs - 生成动态表单输入字段并在数组中收集字段数据

javascript - 当 ng-options 的值和标签相等时出现错误?

javascript - 调用与 Angular 指令绑定(bind)的参数化函数

AngularJS : Prevent error $digest already in progress when calling $scope. $申请()

AngularJS:从父 Controller 访问放置在嵌入指令内的表单的 formController

angularjs - 如何正确安装 Start Angular 模板?

javascript - 我如何使用 Chart.js 中的对象键迭代或从数组中获取所有对象

javascript - 如何在指令中设置 ng-model 的正确范围?

angularjs - Angular 范围函数多次执行