AngularJS: How to run additional code after AngularJS has rendered a template?
First, the right place to mess with rendering are directives. My advice would be to wrap DOM manipulating jQuery plugins by directives like this one.
I had the same problem and came up with this snippet. It uses $watch
and $evalAsync
to ensure your code runs after directives like ng-repeat
have been resolved and templates like {{ value }}
got rendered.
app.directive('name', function() { return { link: function($scope, element, attrs) { // Trigger when number of children changes, // including by directives like ng-repeat var watch = $scope.$watch(function() { return element.children().length; }, function() { // Wait for templates to render $scope.$evalAsync(function() { // Finally, directives are evaluated // and templates are renderer here var children = element.children(); console.log(children); }); }); }, };});
Hope this can help you prevent some struggle.
This post is old, but I change your code to:
scope.$watch("assignments", function (value) {//I change here var val = value || null; if (val) element.dataTable({"bDestroy": true}); });}
see jsfiddle.
I hope it helps you
Following Misko's advice, if you want async operation, then instead of $timeout() (which doesn't work)
$timeout(function () { $scope.assignmentsLoaded(data); }, 1000);
use $evalAsync() (which does work)
$scope.$evalAsync(function() { $scope.assignmentsLoaded(data); } );
Fiddle. I also added a "remove row of data" link that will modify $scope.assignments, simulating a change to the data/model -- to show that changing the data works.
The Runtime section of the Conceptual Overview page explains that evalAsync should be used when you need something to occur outside the current stack frame, but before the browser renders. (Guessing here... "current stack frame" probably includes Angular DOM updates.) Use $timeout if you need something to occur after the browser renders.
However, as you already found out, I don't think there is any need for async operation here.