396

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?

Ian G
  • 498
  • 3
  • 16
user1558259
  • 3,961
  • 3
  • 14
  • 3
  • 2
    Perhaps a more comprehensive overview of directive functions: [Angular directives - when to use compile, controller, pre-link and post-link](http://stackoverflow.com/questions/24615103). – Izhaki Jul 07 '14 at 16:37

4 Answers4

636

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.

Community
  • 1
  • 1
Mark Rajcok
  • 362,217
  • 114
  • 495
  • 492
  • 132
    This explanation should be in the main AngularJS docs or at least a reference to it – Dogoku Nov 19 '12 at 14:20
  • 7
    This is an informative answer but I think that it's difficult to read. Perhaps more punctuation and smaller sentences can help. Overall I'm grateful for the answer. – Marty Cortez Mar 28 '14 at 17:35
  • The $compiler ignores the 'link' attribute in the presence of a 'compile' attribute. But what about in the presence of a 'controller' attribute? Does 'controller' cause the $compiler to ignore either or both 'link' and 'compile' attributes? Is it possible and/or advisable to use a 'compile' together with a 'controller'? – Carl G Apr 29 '14 at 18:17
  • 1
    @CarlG, the presence of a controller attribute has no effect on the $compiler with regards to the link and compile. You can use compile and controller. – Mark Rajcok Apr 30 '14 at 20:38
  • Why is it so hard for everyone else to explain this the way you did? So much simpler than anything else I've read on the subject. – CatDadCode Jul 11 '14 at 02:45
  • 1
    "DOM listeners" are NOT "(i.e., $watch expressions on the scope)". One listens to the DOM for events like `mouseover`, the other to the scope for property changes. Big difference. – Dmitri Zaitsev Nov 12 '15 at 04:13
  • For those of us who need a little bit more help, what is meant by the words "template" and "clone"? – Niko Bellic May 20 '16 at 00:23
  • @MarkRajcok: Can you please look into http://stackoverflow.com/questions/37344476/understanding-step-wise-manual-bootstrapping-of-angularjs. I've seen lot of angular ans from your end so hoping to get some help on this one too. Many thanks :) – Shashank Vivek May 22 '16 at 13:22
57

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).

Pixic
  • 1,345
  • 1
  • 17
  • 29
35
  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

Rahul
  • 866
  • 8
  • 19
  • 19
    "running code before Compilation: use controller". This is incorrect; `compile` will always be executed *before* `controller`. – Izhaki Jul 07 '14 at 16:07
  • You would not (at least not in a straightforward way) be able to access animal from your leopard directive. Child directives can access controller methods in a parent directive, but sibling directives (like in the example above) cannot call one another's controllers. – Benjamin White Jul 10 '14 at 18:06
  • @Benjamin i wanted to convey the idea, however i have edited the answer to show the relation between the directives(child/parent). – Rahul Jul 11 '14 at 10:24
  • 2
    Are leopards really a type of panther? Also, on a side note... Can you have a link -- AND -- a controller in a directive? – Cody Sep 30 '14 at 21:42
  • 1
    yes leopard/jaguars are panthers. and yes you have link and controller within directive. – Rahul Oct 01 '14 at 06:30
  • 1
    From the Angular developer guide: "Best Practice: use controller when you want to expose an API to other directives. Otherwise use link." – Martin van Driel Nov 04 '15 at 09:38
7

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

Sunil Garg
  • 14,608
  • 25
  • 132
  • 189