Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is there a post render callback for Angular JS directive?

Tags:

angularjs

People also ask

What is attrs in AngularJS?

Using attrs you are able to access the attributes defined in your html tag like <fm-rating ng-model="$parent.restaurant.price" symbol="$" readonly="true"> So in this case you will have access to the symbol and readonly attributes.

What is restrict in AngularJS directive?

The restrict option is typically set to: 'A' - only matches attribute name. 'E' - only matches element name. 'C' - only matches class name. 'M' - only matches comment.


If the second parameter, "delay" is not provided, the default behaviour is to execute the function after the DOM has completed rendering. So instead of setTimeout, use $timeout:

$timeout(function () {
    //DOM has finished rendering
});

I had the same problem and I believe the answer really is no. See Miško's comment and some discussion in the group.

Angular can track that all of the function calls it makes to manipulate the DOM are complete, but since those functions could trigger async logic that's still updating the DOM after they return, Angular couldn't be expected to know about it. Any callback Angular gives might work sometimes, but wouldn't be safe to rely on.

We solved this heuristically with a setTimeout, as you did.

(Please keep in mind that not everyone agrees with me - you should read the comments on the links above and see what you think.)


You can use the 'link' function, also known as postLink, which runs after the template is put in.

app.directive('myDirective', function() {
  return {
    link: function(scope, elm, attrs) { /*I run after template is put in */ },
    template: '<b>Hello</b>'
  }
});

Give this a read if you plan on making directives, it's a big help: http://docs.angularjs.org/guide/directive


Although my answer is not related to datatables it addresses the issue of DOM manipulation and e.g. jQuery plugin initialization for directives used on elements which have their contents updated in async manner.

Instead of implementing a timeout one could just add a watch that will listen to content changes (or even additional external triggers).

In my case I used this workaround for initializing a jQuery plugin once the ng-repeat was done which created my inner DOM - in another case I used it for just manipulating the DOM after the scope property was altered at controller. Here is how I did ...

HTML:

<div my-directive my-directive-watch="!!myContent">{{myContent}}</div>

JS:

app.directive('myDirective', [ function(){
    return {
        restrict : 'A',
        scope : {
            myDirectiveWatch : '='
        },
        compile : function(){
            return {
                post : function(scope, element, attributes){

                    scope.$watch('myDirectiveWatch', function(newVal, oldVal){
                        if (newVal !== oldVal) {
                            // Do stuff ...
                        }
                    });

                }
            }
        }
    }
}]);

Note: Instead of just casting the myContent variable to bool at my-directive-watch attribute one could imagine any arbitrary expression there.

Note: Isolating the scope like in the above example can only be done once per element - trying to do this with multiple directives on the same element will result in a $compile:multidir Error - see: https://docs.angularjs.org/error/$compile/multidir