I have a directive attached to a dynamically generated <table>
element inside a template. The directive manipulates the DOM of that table inside a link
function. The problem is that the directive runs before the table is rendered (by evaluating ng-repeat
directives) - the table is empty then.
Question
How can I make sure that the directive is ran after the table has been fully rendered?
<table directive-name>
<tr ng-repeat="...">
<td ng-repeat="..."></td>
</tr>
</table>
module.directive("directiveName", function() {
return {
scope: "A",
link: function(scope, element, attributes) {
/* I need to be sure that the table is already fully
rendered when this code runs */
}
};
});
AngularJS directives are extended HTML attributes with the prefix ng- . The ng-app directive initializes an AngularJS application. The ng-init directive initializes application data. The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.
The ng-init Directive is used to initialize AngularJS Application data. It defines the initial value for an AngularJS application and assigns values to the variables. The ng-init directive defines initial values and variables for an AngularJS application.
A controller is usually used to contain and maintain the logic for your view, which gets bound to your view via $scope. A directive is something that you might use repeatedly and is called in your view directly through the directive name which you can pass in as an attribute.
You can't, in a general sense, be ever "fully sure" by just having a directive on the <table>
element.
But you can be sure in certain cases. In your case, if the inner content is ng-repeat
-ed, then if the array of items over which ngRepeat
works is ready, then the actual DOM elements will be ready at the end of the digest cycle. You can capture it after $timeout
with 0 delay:
link: function(scope, element){
$timeout(function(){
console.log(element.find("tr").length); // will be > 0
})
}
But, in a general sense, you can't be certain to capture the contents. What if the ngRepeat
ed array is not there yet? Or what if there is an ng-include
instead?
<table directive-name ng-include="'templates/tr.html'">
</table>
Or, what if there was a custom directive that worked differently than ngRepeat
does?
But if you have full control of the contents, one possible way to know is to include some helper directive as the innermost/last element, and have it contact its parent directiveName
when it's linked:
<table directive-name>
<tr ng-repeat="...">
<td ng-repeat="...">
<directive-name-helper ng-if="$last">
</td>
</tr>
</table>
.directive("directiveNameHelper", function(){
return {
require: "?^directiveName",
link: function(scope, element, attrs, ctrl){
if (!ctrl) return;
ctrl.notifyDone();
}
}
})
Try wrapping in a $timeout
the code from your link function as it will execute after the DOM is rendered.
$timeout(function () {
//do your stuff here as the DOM has finished rendering already
});
Don't forget to inject $timeout
in your directive:
.directive("directiveName", function($timeout) {
There are plenty of alternatives but I think this one is cleaner as the $timeout executes after the rendering engine has finished its job.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With