Neither $scope.$evalAsync() or $timeout(fn, 0) worked reliably for me.
I had to combine the two. I made a directive and also put a priority higher than the default value for good measure. Here's a directive for it (Note I use ngInject to inject dependencies):
app.directive('postrenderAction', postrenderAction);
/* @ngInject */
function postrenderAction($timeout) {
// ### Directive Interface
// Defines base properties for the directive.
var directive = {
restrict: 'A',
priority: 101,
link: link
};
return directive;
// ### Link Function
// Provides functionality for the directive during the DOM building/data binding stage.
function link(scope, element, attrs) {
$timeout(function() {
scope.$evalAsync(attrs.postrenderAction);
}, 0);
}
}
To call the directive, you would do this:
<div postrender-action="functionToRun()"></div>
If you want to call it after an ng-repeat is done running, I added an empty span in my ng-repeat and ng-if="$last":
<li ng-repeat="item in list">
<!-- Do stuff with list -->
...
<!-- Fire function after the last element is rendered -->
<span ng-if="$last" postrender-action="$ctrl.postRender()"></span>
</li>