Deep Dive into Angular Directives

31 / May / 2016 by Mahima Agrawal 0 comments

Angular directives are very useful in any angularJs application in order to make code simple and easily handled by a UI Developer. As an angular developer we all use directives frequently but most of us are not aware about the execution cycle of directives that how they work internally. Directives have several inbuilt functions by which we can achieve many functionalities in a simple and concise way.

Thus it is very important to understand their life cycle and how they are created and destroyed. There are four life cycle functions and each has it’s own importance and order of execution.

Let’s have a look at these execution cycle of functions:

Compile

This function executes only once per and before all other functions. Suppose we have a situation in which we are using our directive inside ng-repeat and we need to execute certain initialization etc. only once then we can write it in compile function.

Controller

Let’s assume we have a situation in which we are using a nested directive,  i.e directive inside another directive, and we want to communicate between them. Then a controller can solve that problem.

In simplest word parent,child and sibling directives can communicate to each other by using controller function. Controllers are similar to any other angular controller for our views.

Pre-link

Imagine we have a situation in which we want to use a scope variable of parent directive in child directive. If we define that scope variable in parent’s link function(which is like post-link function), and we fetch that variable into child link function then we will not be able to access  that variable and it will be  undefined, since the execution flow of link function is from child to parent.
But we can solve this issue by defining that scope variable into parent pre-link function and that variable will be fetched properly in child link or pre-link function since pre-link function of parent always executes before link or pre-link function of child.

Post-link

This function is the main work area of directive, and this is where most of us work. It is the same as a link function.

Example:

index.html with three directives(layout as parent, section as child and subsection as grand child)


<div ng-app="directiveApp">
  <div layout-dir>Layout
    <div section-dir>Section
        <div sub-section-dir>Sub Section
        </div>
    </div>
  </div>
</div>

Layout directive which is parent of section and subsection directives:

var directiveApp = angular.module("directiveApp",[]);
directiveApp.directive('layoutDir', function(){
    return {
        restrict: 'EA',
        compile: function compile(){
            console.log('layout compile function');
            return {
                post:function(scope, element, attrs){
                    console.log('layout post link function');

                },
                pre: function(scope){
                    console.log('layout pre link function');
                }
            }
        },
        controller: function($scope){
            console.log('layout controller');
        }
    };
});

Section directive which is parent of sub section directive and child of layout directive:

directiveApp.directive('sectionDir', function(){
    return {
        restrict: 'EA',
        compile: function(tElement, tAttrs){
                console.log('section compile function');
                return {
                    post:function(scope, element, attrs, parentCtrl){
                        console.log('section post link function');
                    },
                    pre: function(scope){
                        console.log('section pre link function');
                    }
                }
        },
        controller: function($scope){
            console.log('section controller');
        }

    };
});

Sub Section directive which is child of Section directive and grand child of layout directive:

directiveApp.directive('subSectionDir', function(){
    return {
        restrict: 'EA',
        compile: function(){
            console.log('subSection compile function');
            return {
                post:function(scope, element, attrs, parentCtrl){
                    console.log('subSection post link function');

                },
                pre: function(scope){
                    console.log('subSection pre link function');
                }
            }
        },
        controller: function($scope){
            console.log('subSection controller');
        }

    };
});

If we run the above code we will get the following output:

layout compile function

section compile function

subSection compile function

layout controller

layout pre link function

section controller

section pre link function

subSection controller

subSection pre link function

subSection post link function

section post link function

layout post link function

The execution order of the functions within a directive, and relative to other directives, is as follows:

largeImage

Parent and child directives also can communicate to each other by requiring parent directive into child directive and calling the functions which are defined in parent controller. See the below code block:

Layout directive

Controller is having addSection and addSubSection functions which will be called by corresponding child directives:

directiveApp.directive('layoutDir', function(){
    return {
        restrict: 'EA',
        compile: function compile(){
            console.log('layout compile function');
            return {
                post:function(scope, element, attrs){

                    console.log('layout post link function');
                    element.bind('mouseenter', function(){
                        console.log('mouse enter', scope.layoutSection);
                    });

                },
                pre: function(scope){
                    console.log('layout pre link function');
                }
            }
        },
        controller: function($scope){
            $scope.layoutSection = [];
            console.log('layout controller');
            this.addSection = function(){
                $scope.layoutSection.push('section');
            };
            this.addSubSection = function(){
                $scope.layoutSection.push('sub section');
            };
        }

    };
});

Section directive

This directive requires parent directive and calls addSection function of layout directive.

directiveApp.directive('sectionDir', function(){
    return {
        require: "^layoutDir",
        restrict: 'EA',
        compile: function(tElement, tAttrs){
                console.log('section compile function');
                return {
                    post:function(scope, element, attrs, parentCtrl){

                        console.log('section post link function');
                        parentCtrl.addSection();

                    },
                    pre: function(scope){
                        console.log('section pre link function');
                    }
                }

        },
        controller: function($scope){
            console.log('section controller');

        }

    };
});

SubSection directive

This directive requires parent directive and calls addSubSection function of layout directive.

directiveApp.directive('subSectionDir', function(){
    return {
        require: "^layoutDir",
        restrict: 'EA',
        compile: function(){
            console.log('subSectio compile function');
            return {
                post:function(scope, element, attrs, parentCtrl){
                    console.log('subSectio post link function');
                    parentCtrl.addSubSection();

                },
                pre: function(scope){
                    console.log('subSectio pre link function');
                }
            }
        },
        controller: function($scope){
            console.log('subSection controller');
        }

    };
});

So This is basically what there is to know about a directive execution cycle. Hope this will help you in understanding  execution cycle of directive and will enhance usability of your directives :-)

FOUND THIS USEFUL? SHARE IT

Leave a comment -