Difference between the 'controller', 'link' and 'compile' functions when defining a directive

Some places seem to use the controller function for directive logic and others use link. The tabs example on the angular homepage uses controller for one and link for another directive. What is the difference between the two?


I'm going to expand your question a bit and also include the compile function.

  • compile function - use for template DOM manipulation (i.e., manipulation of tElement = template element), hence manipulations that apply to all DOM clones of the template associated with the directive. (If you also need a link function (or pre and post link functions), and you defined a compile function, the compile function must return the link function(s) because the 'link' attribute is ignored if the 'compile' attribute is defined.)

  • link function - normally use for registering listener callbacks (i.e., $watch expressions on the scope) as well as updating the DOM (i.e., manipulation of iElement = individual instance element). It is executed after the template has been cloned. E.g., inside an <li ng-repeat...>, the link function is executed after the <li> template (tElement) has been cloned (into an iElement) for that particular <li> element. A $watch allows a directive to be notified of scope property changes (a scope is associated with each instance), which allows the directive to render an updated instance value to the DOM.

  • controller function - must be used when another directive needs to interact with this directive. E.g., on the AngularJS home page, the pane directive needs to add itself to the scope maintained by the tabs directive, hence the tabs directive needs to define a controller method (think API) that the pane directive can access/call.

    For a more in-depth explanation of the tabs and pane directives, and why the tabs directive creates a function on its controller using this (rather than on $scope), please see 'this' vs $scope in AngularJS controllers.

In general, you can put methods, $watches, etc. into either the directive's controller or link function. The controller will run first, which sometimes matters (see this fiddle which logs when the ctrl and link functions run with two nested directives). As Josh mentioned in a comment, you may want to put scope-manipulation functions inside a controller just for consistency with the rest of the framework.


As complement to Mark's answer, the compile function does not have access to scope, but the link function does.

I really recommend this video; Writing Directives by Misko Hevery (the father of AngularJS), where he describes differences and some techniques. (Difference between compile function and link function at 14:41 mark in the video).


  1. running code before Compilation : use controller
  2. running code after Compilation : use Link

Angular convention : write business logic in controller and DOM manipulation in link.

Apart from this you can call one controller function from link function of another directive.For example you have 3 custom directives

<animal>
<panther>
<leopard></leopard>
</panther> 
</animal>

and you want to access animal from inside of "leopard" directive.

http://egghead.io/lessons/angularjs-directive-communication will be helpful to know about inter-directive communication


compile function -

  1. is called before the controller and link function.
  2. In compile function, you have the original template DOM so you can make changes on original DOM before AngularJS creates an instance of it and before a scope is created
  3. ng-repeat is perfect example - original syntax is template element, the repeated elements in HTML are instances
  4. There can be multiple element instances and only one template element
  5. Scope is not available yet
  6. Compile function can return function and object
  7. returning a (post-link) function - is equivalent to registering the linking function via the link property of the config object when the compile function is empty.
  8. returning an object with function(s) registered via pre and post properties - allows you to control when a linking function should be called during the linking phase. See info about pre-linking and post-linking functions below.

syntax

function compile(tElement, tAttrs, transclude) { ... }

controller

  1. called after the compile function
  2. scope is available here
  3. can be accessed by other directives (see require attribute)

pre - link

  1. The link function is responsible for registering DOM listeners as well as updating the DOM. It is executed after the template has been cloned. This is where most of the directive logic will be put.

  2. You can update the dom in the controller using angular.element but this is not recommended as the element is provided in the link function

  3. Pre-link function is used to implement logic that runs when angular js has already compiled the child elements but before any of the child element's post link have been called

post-link

  1. directive that only has link function, angular treats the function as a post link

  2. post will be executed after compile, controller and pre-link funciton, so that's why this is considered the safest and default place to add your directive logic