How can run a method $scope.myWork()
after render template? I want to set the $scope.value
and after that I need to change something with JQuery (eg. in DOM of template content). $scope.$watch('value', function (){....})
is working "before" render (DOM of template is not available yet). Thanks.

- 1,161
- 4
- 11
- 16
5 Answers
Create a directive that runs your code in the link function. The link function is called after the template is built.
See ng-click to get an idea.

- 7,932
- 7
- 61
- 93

- 10,978
- 4
- 48
- 31
-
There is my example, that doesn't work - http://jsfiddle.net/C6SUv/7/ (why isn't $scope.afterRender call after each render?). – user1595465 Aug 14 '12 at 15:07
-
because the link function is called once after it element is rendered, not after each render of angular. Why you can't create directives do make the changes that you need with jQuery and update angular? Manipulating DOM inside of controllers isn't a good practice – Renan Tomal Fernandes Aug 14 '12 at 16:56
-
Hmmmmm. I have to scroll div with fix height. I have buttons for moving cursor in list of fields. I set $scope.value in ngClick and after that I need to scroll on right position (via scrollTop). That's the reason, why I want to manipulate with DOM inside of controller. Any idea? – user1595465 Aug 14 '12 at 17:10
-
See if `$anchorScroll` can do the job or create a service for this(to make your controller more testable). Making a directive that set the actual 'top' of the div into a variable in your controller and a service to scroll will be a good match. – Renan Tomal Fernandes Aug 14 '12 at 17:15
-
Sorry, but I still don't understand. I have BODY and inside DIV with fix height with scrollbar. The content of DIV is list (with 5000 rows), that is managed via buttons (for moving cursor up and down). I think $anchorScroll isn't solution for me. – user1595465 Aug 14 '12 at 17:31
-
2Maybe you want to create a directive with a controller in the DIV and in each row you can add a directive that in the link function(after render) it use the controller from the DIV passing it 'top' and the controller scroll to it. In the childs(rows) you will use `require: '^DIVdirectiveName'` to get the controller. See this update fiddle http://jsfiddle.net/C6SUv/8/ – Renan Tomal Fernandes Aug 14 '12 at 22:34
-
Renan's approach by putting in an additional directive looks pretty interesting. I could see it working in some of my situations. Still weird that there isn't a solution that is more to the point of what apparently everybody is running into. – Wilfred Springer Aug 18 '12 at 20:58
-
@WilfredSpringer - all dom manipulations should be in a directive, that's what the docs recommend – Neil Jan 08 '13 at 16:12
I use terminal
and transclude
in a attribute directive to call a scoped method after a model is updated and view is rendered (in my case to resize a iframe after a $Resource.query):
.directive('postRender', [ '$timeout', function($timeout) {
var def = {
restrict : 'A',
terminal : true,
transclude : true,
link : function(scope, element, attrs) {
$timeout(scope.resize, 0); //Calling a scoped method
}
};
return def;
}])
The $timeout is black magic. It should be possible to declare the JS method as the attribute value and $parse it.
So I use it in a ng-repeat
(in my case a tree is rendered recursively):
<div post-render ng-repeat="r in regions | orderBy:'name'" ng-include="'tree_region_renderer.html'">

- 1,214
- 12
- 13
I also had this problem, other solutions didn't work well for me, and it seemed like the kind of thing Protractor must have solved. A quick review of Protractor's client-side scripts shows it uses angular.getTestability(element)
to know when to actually run the tests. The method waits until there are no pending timeouts or http requests and then runs your callback. Here's my directive:
export function afterRender ($timeout) {
"ngInject";
return {
restrict: 'A',
terminal: true,
link: function (scope, element, attrs) {
angular.getTestability(element).whenStable(function() {
console.log('[rendered]');
});
}
};
}

- 40,459
- 37
- 151
- 246
-
1Since you are running inside the Angular app, you can simply inject `$browser` and register a callback with its `notifyWhenNoOutstandingRequests()` method. Note, though, that this is relying on some undocumented, private APIs and might break without notice. – gkalpak Feb 25 '16 at 11:46
-
In my case I was driving the browser from a script. In the future I'll remove the directive and call whenStable() from the driver instead – joeforker Mar 22 '19 at 21:48
Jens answer above will work , but note that on newer AngularJS versions (for example 1.2.3) you cannot have that postRender directive in combination with ng-repeat as attributes on the same tag since they both have transclude: true. In that case you either must remove transclude or have a separate tag with the postRender directive attribute.
Also be aware of priority of attributes when using terminal: true since you might end up having an attribute non- effective due to a higher priorotized one on the same tag.

- 21
- 2
I found this page when looking for a way to profile DOM rendering. I found a far simple solution which is working for my use case.
Attach an ng-init handler to the DOM element and in the handler function, use $timeout to yield execution. Example:
HTML:
<div ng-init="foo()">
JS:
$scope.foo = function() {
$timeout(function() {
// This code runs after the DOM renders
});
});

- 11