Angular directives – Difference between controller and link

Angular directives can be a black hole of thoughts, and one of those being, “where do I put code, in ‘controller’ or ‘link’?”

The short short answer: ‘link’.

The longer short answer: Ask yourself “when do I want my code to run?”

  • Before compilation? – Controller
  • After compilation? – Link

What does this mean? While I would never condone putting DOM manipulation in an angular controller, I see it constantly, and its important to know what is actually going on and when functions are run. Example Plunkr: http://plnkr.co/edit/k5fHMU?p=preview

 But, but, but, more details please!

Ok, ok, fair enough. Couple of things to note:




  1. controller ‘$scope’ and link ‘scope’ are the same thing. The difference is paramaters sent to the controller get there through Dependency Injection (so calling it ‘$scope’ is required), where parameters sent to link are standard order based funcitons.  All of the angular examples will use ‘scope’ when in the context, but I usually call it $scope for sanity reasons: http://plnkr.co/edit/lqcoJj?p=preview
  2. the $scope/scope in this example is simply the one passed in from the parent controller.
  3. ‘link’ in directives are actually the ‘post-link’ function (see rendering pipeline below). Since pre-link is rarely used, the ‘link’ option is just a shortcut to setting up a ‘post-link’ function.

So, whats a real world example? Well, when I’m deciding, I go by this:

  • “Am I just doing template and scope things?” – goes into controller
  • “Am I adding some coolbeans jquery library?” – goes in link

 But, why!?!?!

Well, here is a great example of the angular compilation and linking pipeline: http://plnkr.co/edit/CW7cF0?p=preview

What this is telling you is that all child directives link functions get executed before the parent functions link functions. So something like the below will not work:

So why do we even have a ‘controller’ in the directive, seems dumb :-p

So we can do awesome stuff like using one directives controller in another. We simply set something we want to “this” and get it using the “require” option in the directive.

Many thanks to Josh Harris for his code reviews and awesome pipeline example above!

Share This:

Leave a Reply

Your email address will not be published. Required fields are marked *