Friday, August 16, 2013

Angular Directives - Compile vs link

In this post i will be talking more on directives.
In the previous post(http://softtechhelp.blogspot.in/2013/07/compile-vs-link-and-bootstrap-process.html) we talked the difference between compile and link and seen it by manual bootstrapping the Angular. In today's post we will try to visualize the same compile and link, while using Directives. understanding Compile and link becomes very important when you are working with directives and that the most practical case when you actually use the concept of compile and link.
Before starting small introduction of Directive -
It is a way provided by Angular to make your HTML more dynamic and rich. Using Directive we can create our component and can plug it anywhere in out HTML or can provide it as 3rd party component.
Directives has camel case notation. In HTML we access it by '-' dashcased. It is Simply precedence given by Jquery and others that HTML is case insensitive so have names separated by '-', but in javascript we will have to use special characters to support it. Hence to support both HTML and javascript we follow this convention in Angular Directives.
Without wasting any more time on theory, let begin our practical scenario and see how it works. Here is an example -
<body ng-controller="Demo">
      Name: <input ng-model="name" />
      <div>
          Hello <span ng-bind="name"></span>
      </div>    
      <div demo-greet></div>
  </body>

myApp.directive('demoGreet', function ($parse) {
return {
    //compile fn doesnt have access to scope.
    //event in the bootstrap var compositeLinkFn = $compile($rootElement);, we dont have access to scope
    compile: function compileFn(cElemtn, attrs) {
       console.log('compileFn(', cElemtn, attrs, ')');
       cElemtn.addClass('compiling');
       return function linkFn(scope, lElement, attrs) {
          console.log('linkFn(', scope, lElement, attrs, ')', cElemtn == lElement);

          lElement.text('Hello World');
       }
     }
  }
});

In the above example we have a directive "demoGreet", which has a compile function which returns link function. I have put in logging to see how many elements of that type got created. I have cElemtn(Compile)and IElement(Link) to see if both are same or not. Also ihave logged how many times does the compile and link get executed. Lets try to browse the page and see the console in chrome. This is how it looks like -


The above output shows, compile and link are same. If you see both are executed once and also true shows that the elements are also same. Well, If so, why do we have 2 different functions in Angular? Actually there is difference between the two . The difference is - compile doesn't have access to scope. In the previous article also we mentioned, after compile only while using link, scope comes into the picture. To see the actual difference we will try to use ng-repeat tag.

modify the HTML like this and see the output difference-
<div demo-greet ng-repeat="i in [1,0]"></div>
This time Compile function gets executed only once, whereas link function executed once for every iteration of repeater. Once we have repeater, the two are no longer similar.
Also if you see, both the elements has class "compiling" when compile function got executed only once. That is because the compile function works on template. It modified the template, which ng-repeat use to create new instance.
Compile function is used to modify the template, and link is more for linking with the objects.

I hope it clarifies the difference between two.