3

在下面的代碼中,角度指令'myscroll'如何知道正在創建什麼ng-repeat元素?在角度指令中獲取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") }) 

     } 
    } 
}) 
+0

ng-repeat爲每個重複元素創建一個新的子作用域。只有在該範圍內纔是$最後一個屬性。但即使如此,當我所知的所有元素都被渲染出來時,您仍然無法得到通知。 –

+0

您是否找到了解決方案?這曾經工作,但不再是了! – Dine

回答

1

一個簡單的方法來做到這一點是創建一個名爲新指令「重複,做了」,並用它在「NG重複」的。然後你可以通知'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); 
      } 
     } 
     }; 
    }]) 
1

就在就這個問題的情況下別人跌倒,我想分享我的解決方案。德魯茲的回答指出我的方向是正確的,但我採取了更加「優雅」的方式。

爲了給你提供上下文,我需要使用ng-repeat這個系統來填充選擇下拉列表中的選項。與jQuery Chosen插件(順便說一句,美麗的自動完成/搜索下拉插件)ng插件不兼容,我需要在所有選項完成渲染後初始化插件。

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重複指令。由於這是一個非侵入性的加法,因此我毫不猶豫地將其用於ng-repeat的所有用途。

在函數本身中,我沒有使用$elem.parent().scope()(它可以 - 而且在大多數情況下會工作),而是使用Angular的$scope.$parent來獲取父上下文。

然後我廣播自定義事件(event:repeat-done),並將最後呈現的repeat元素作爲參數傳遞給父範圍。

然後,我可以在自動完成指令中選取此事件,並在完全呈現的select元素上初始化我選擇的插件!

然後,這種技術可以在任何時候需要檢測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以使事件冒泡而不是減少。