After my initial struggle with the link and controller functions and reading quite a lot about them, I think now I have the answer.
First lets understand,
How do angular directives work in a nutshell:
-
We begin with a template (as a string or loaded to a string)
var templateString = '<div my-directive>{{5 + 10}}</div>'; -
Now, this
templateStringis wrapped as an angular elementvar el = angular.element(templateString); -
With
el, now we compile it with$compileto get back the link function.var l = $compile(el)Here is what happens,
$compilewalks through the whole template and collects all the directives that it recognizes.- All the directives that are discovered are compiled recursively and their
linkfunctions are collected. - Then, all the
linkfunctions are wrapped in a newlinkfunction and returned asl.
-
Finally, we provide
scopefunction to thisl(link) function which further executes the wrapped link functions with thisscopeand their corresponding elements.l(scope) -
This adds the
templateas a new node to theDOMand invokescontrollerwhich adds its watches to the scope which is shared with the template in DOM.

Comparing compile vs link vs controller :
-
Every directive is compiled only once and link function is retained for re-use. Therefore, if there’s something applicable to all instances of a directive should be performed inside directive’s
compilefunction. -
Now, after compilation we have
linkfunction which is executed while attaching the template to the DOM. So, therefore we perform everything that is specific to every instance of the directive. For eg: attaching events, mutating the template based on scope, etc. -
Finally, the controller is meant to be available to be live and reactive while the directive works on the
DOM(after getting attached). Therefore:(1) After setting up the view[V] (i.e. template) with link.
$scopeis our [M] and$controlleris our [C] in M V C(2) Take advantage the 2-way binding with $scope by setting up watches.
(3)
$scopewatches are expected to be added in the controller since this is what is watching the template during run-time.(4) Finally,
controlleris also used to be able to communicate among related directives. (LikemyTabsexample in https://docs.angularjs.org/guide/directive)(5) It’s true that we could’ve done all this in the
linkfunction as well but its about separation of concerns.
Therefore, finally we have the following which fits all the pieces perfectly :
