在Angular指令中完成ng-repeat

3
在下面的代码中,Angular指令'myscroll'如何知道正在创建哪些ng-repeat元素?
<myscroll>
     <div ng-repeat="a in arr">{{a}}</div>
</myscroll>

我知道 $last 事件不会向父指令触发,我该如何解决这个问题?
myapp.directive("myscroll", function () {
    return{
        restrict: "E",
        transclude: true,
        template: "<span class='left'></span><div class='mask' ng-transclude></div><span class='right'></span>",
        link: function (scope, element, attr) {

            scope.$watch("$last",function(){ console.log("ng-repeat rendered") })

        }
    }
})

ng-repeat为每个重复的元素创建一个新的子作用域。只有在该作用域中才有$last属性。但即便如此,据我所知,你也无法真正得到所有元素都已呈现的通知。 - Liviu T.
你找到解决方案了吗?这以前可以用,但现在不行了! - Dine
2个回答

1

以防其他人遇到同样的问题,我想分享我的解决方案。dluz的答案指引了我正确的方向,但我采用了更加“优雅”的方法。

为了让你了解背景,我需要使用ng-repeat将选项填充到下拉选择框中。ng-options与jQuery Chosen插件(一个美丽的自动完成/搜索下拉插件!)不兼容,我需要在所有选项渲染完成后初始化插件。

HTML:

<select auto-complete ng-model="stuff">
    <option ng-repeat="item in items" value="{{ item.value }}">{{ item.name }}</option>
</select>

JavaScript:

// Extension of built-in ngRepeat directive - broadcasts to its parent when it is finished.
// Passes the last element rendered as an event parameter.
app.directive('ngRepeat', function () {
    return {
        restrict: 'A',
        link: function ($scope, $elem, $attrs) {
            if ($scope.$last)
                $scope.$parent.$broadcast('event:repeat-done', $elem);
        }
    };
});

// My directive for working with the Chosen plugin.
app.directive('autoComplete', function () {
    return {
        restrict: 'A',
        link: function ($scope, $elem, $attrs) {
            $scope.$on('event:repeat-done', function () {
                setTimeout(function () {
                    if (!$elem.children(':first-child').is('[disabled]'))
                        $elem.prepend('<option disabled="disabled"></option>');
                    $elem.chosen({ disable_search_threshold: 10, width: '100%' });
                    $elem.trigger('chosen:updated');
                });
            });
        }
    };
});

如您所见,我只是用我的广播函数扩展了内置的ng-repeat指令。由于这是一种非侵入性的添加方式,因此我没有任何顾虑将其实现到所有使用ng-repeat的情况中。
在函数本身中,我使用Angular的$scope.$parent来获取父上下文,而不是查看$elem.parent().scope()(这在大多数情况下可以工作)。
然后我广播一个自定义事件(event:repeat-done),并将最后呈现的重复元素作为参数传递给父级作用域。
然后我可以在我的自动完成指令中捕获此事件,并在完全呈现的选择元素上初始化我的Chosen插件!
这种技术可以通用地应用于任何需要检测ng-repeat指令何时完成的情况。对于您的示例:
myapp.directive("myscroll", function () {
    return{
        restrict: "E",
        transclude: true,
        template: "<span class='left'></span><div class='mask' ng-transclude></div><span class='right'></span>",
        link: function (scope, element, attr) {
            scope.$on("event:repeat-done",function(){ console.log("ng-repeat rendered") })
        }
    }
})

编辑:对于某些情况,检测这些事件一直到rootScope可能是有益的。如果是这种情况,你可以用$scope.$emit替换$scope.$parent.$broadcast,让事件向上传递而不是向下传递。


1
一种简单的方法是创建一个名为'repeat-done'的新指令,并在'ng-repeat'所在的位置使用它。然后,您可以通知'myscroll'指令(父作用域)您需要的任何内容。
<myscroll>
     <div ng-repeat="a in arr" repeat-done>{{a}}</div>
</myscroll>

myapp.directive('repeatDone', [function () {
  return {
    restrict: 'A',
     link: function (scope, element, iAttrs) {

          var parentScope = element.parent().scope();

          if (scope.$last){
               // ng-repeat is completed and you now have access to 'myscroll' scope
               console.log(parentScope);   
          }
        }
      };
    }])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接