What else happens between these function calls?

The various directive functions are executed from within two other angular functions called $compile (where the directive's compile is executed) and an internal function called nodeLinkFn (where the directive's controller , preLink and postLink are executed). Various things happen within the angular function before and after the directive functions are called. Perhaps most notably is the child recursion. The following simplified illustration shows key steps within the compile and link phases:

To demonstrate the these steps, let's use the following HTML markup:

<div ng-repeat="i in [0,1,2]"> <my-element> <div>Inner content</div> </my-element> </div>

With the following directive:

myApp.directive( 'myElement', function() { return { restrict: 'EA', transclude: true, template: '<div>{{label}}<div ng-transclude></div></div>' } });

Compile

The compile API looks like so:

compile: function compile( tElement, tAttributes ) { ... }

Often the parameters are prefixed with t to signify the elements and attributes provided are those of the source template, rather than that of the instance.

Prior to the call to compile transcluded content (if any) is removed, and the template is applied to the markup. Thus, the element provided to the compile function will look like so:

<my-element> <div> "{{label}}" <div ng-transclude></div> </div> </my-element>

Notice that the transcluded content is not re-inserted at this point.

Following the call to the directive's .compile , Angular will traverse all child elements, including those that may have just been introduced by the directive (the template elements, for instance).

Instance creation

In our case, three instances of the source template above will be created (by ng-repeat ). Thus, the following sequence will execute three times, once per instance.

Controller

The controller API involves:

controller: function( $scope, $element, $attrs, $transclude ) { ... }

Entering the link phase, the link function returned via $compile is now provided with a scope.

First, the link function create a child scope ( scope: true ) or an isolated scope ( scope: {...} ) if requested.

The controller is then executed, provided with the scope of the instance element.

Pre-link

The pre-link API looks like so:

function preLink( scope, element, attributes, controller ) { ... }

Virtually nothing happens between the call to the directive's .controller and the .preLink function. Angular still provide recommendation as to how each should be used.

Following the .preLink call, the link function will traverse each child element - calling the correct link function and attaching to it the current scope (which serves as the parent scope for child elements).

Post-link

The post-link API is similar to that of the pre-link function:

function postLink( scope, element, attributes, controller ) { ... }

Perhaps worth noticing that once a directive's .postLink function is called, the link process of all its children elements has completed, including all the children's .postLink functions.

This means that by the time .postLink is called, the children are 'live' are ready. This includes:

data binding

transclusion applied

scope attached

The template at this stage will thus look like so: