ng-repeat onFinishRender directive AngularJs

There are some specific scenarios specially when you manipulate the DOM with ng-repeat directive. Lets imagine we have a code that prints a list of element using an ng-repeat. In your controller you have a code to instantiate a bootstrap tooltip for all the elements that are going to be rendered when the ng-repeat is compiled by AngularJs. As a best practice it is better to place this type of code in a directive, for this example purpose, we are going to keep it simple and leave it in the controller.

$('.yourDynamicallyCreatedElements').tooltip("text")

 
onFinishRender directive AngularJs

onFinishRender directive AngularJs

The problem here is that the code within the controller is executed before angular compiles the ng-repear, before the DOM elements are part of the HTML. It is hard if not impossible, to find a place to bind events to the elements of an ng-repeat, since angular doesn’t provide any event that fires when the elements finish rendering. Here we are going to share haw to create an event onFinishRender directive.

I created this simple directive to capture the moment that the last element is inserted in the DOM,  with this we will be able to call a JavaScript method after the ng-repeat completes the rendering process.

this is the View:

<ul>
  <li ng-repeat="item in items" on-finish-render="callMyCustomMethod()">
      dummy Text
  </li>
</ul>

 
 

Here is the onFinishRender directive:

 

.directive('onFinishRender',['$timeout', '$parse', function ($timeout, $parse) {
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            if (scope.$last === true) {
                $timeout(function () {
                    scope.$emit('ngRepeatFinished');
                    if(!!attr.onFinishRender){
                      $parse(attr.onFinishRender)(scope);
                    }
                });
            }
        }
    }
}])

We going to inject the $timeout service to emit an event and include it within the angular digest process, and the $parse service, to include our method within the scope when the ng-repeat finished;

Basically what we going to do is get when the scope.$last variable is equal true, this mean that this is the last time the ng-repeat going to render an element.

Then we going to send an event with scope.$emit(‘yourCustomEventName’).

Then we going to parse the method within the scope

In case we want to capture the event in the controller, we can use the $scope.$on() function.


            //this is the code to capture the emited event
            $scope.$on('ngRepeatFinished', function(ngRepeatFinishedEvent) {
                        //you also get the actual event object, ngRepeatFinishedEvent
                        //do stuff, execute functions -- whatever...
             });

 

book

Book Tip

ng-book – The Complete Book on AngularJS
Ready to master AngularJS? What if you could master the entire framework – with solid foundations – in less time without beating your head against a wall?


Amazon

 

Here is a working example in jsFfidle. In this exaple we also capture the onStartRender event

Hope this was helpful 😉