ngRepeat打破了指令的功能

Dan*_*iel 2 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");
               };
            }
        }
    }]);
    
    Run Code Online (Sandbox Code Playgroud)
  • 另一个是可重用的文本字段组件,定义为具有隔离范围的指令,它使用验证指令(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>'
    
       }
    });
    
    Run Code Online (Sandbox Code Playgroud)

我面临的问题是,当我在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>
Run Code Online (Sandbox Code Playgroud)

我知道ngRepeat创建了一个新的IsolatedScope,但我不明白这对我的指令在这种情况下是如何影响的,以及这个问题的正确解决方案是什么.

我准备了一个JS小提琴来最好地描述我的问题.

Ism*_*OUH 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);
      };
    }
Run Code Online (Sandbox Code Playgroud)

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