ngRepeat打破了指令的功能

时间:2016-06-29 14:03:56

标签: javascript angularjs

我有两个连接在一起的指令(提供最少的代码示例):

  • 一个用于验证目的( apValidation )。

    module.directive('apValidation', ['$compile', function($compile){
        return {
            restrict: 'A',
            compile: function (element) {
            element.removeAttr('ap-validation');   // to avoid infinite compilation
            element.attr('ng-blur', 'testMe()');   // this method has to be called for the validation to happen
            var fn = $compile(element);
                return function (scope) {
                    fn(scope);
                  };
            },
            controller: function ($scope, $attrs) {
               $scope.testMe = function () {
                   alert("Validating current text field");
               };
            }
        }
    }]);
    
  • 另一个是可重用的文本字段组件,定义为具有独立范围的指令,它使用验证指令( apTextField )。

    module.directive('apTextField', function(){
        return{
            restrict: 'E',
            replace:true,
            scope: {
                name: '@',
                label: '@'
            },
        template: '<div>{{label}}: <input type="text" id="someId" name="{{name}}" ap-validation></input></div>'
    
       }
    });
    

我面临的问题是,当我在 ngRepeat 上下文中使用我的文本字段指令时,不知何故验证功能,即由此处的模糊事件触发案件,不再被召唤。 但是,验证在ngRepeat上下文之外正常工作。

<div ng-app="my-app" ng-controller="MainController">
<div>
     Without ng-repeat<br>
     <div ng-init="field = {name: 'age', label: 'Age'}">
       <ap-text-field 
                label={{field.label}}
                name="{{field.name}}">
              </ap-text-field>  
     </div><br>

     With ng-repeat<br>

        <div ng-repeat="field in fields">
              <ap-text-field 
                label={{field.label}}
                name="{{field.name}}">
              </ap-text-field>  
        </div>
</div>

我知道ngRepeat会创建一个新的IsolatedScope,但我不明白这会如何影响我的指令,以及这个问题的正确解决方案是什么。

我已准备好JS Fiddle来最好地描述我的问题。

1 个答案:

答案 0 :(得分:5)

原因是ngRepeat指令已经编译了它的转发器并将其从DOM中删除(在$ watchCollection()回调期间重新插入);因此,以下代码var fn = $compile(element);编译从DOM中删除的元素。因此,解决方案是编译提供给返回回调的新element

compile: function (element) {
      element.removeAttr('ap-validation');   // to avoid infinite compilation
      element.attr('ng-blur', 'testMe()');   // this method has to be called for the validation to happen
      return function (scope, element) {
                            //^ the new element
        $compile(element)(scope);
      };
    }

演示: https://jsfiddle.net/g3yeg5xp/