Ben Nadel
On User Experience (UX) Design, JavaScript, ColdFusion, Node.js, Life, and Love.
Ben Nadel at the New York Javascript Meetup (Aug. 2010) with: Rebecca Murphey and Adam Sontag
Ben Nadel at the New York Javascript Meetup (Aug. 2010) with: Rebecca Murphey@rmurphey ) and Adam Sontag@ajpiano )

The "Post-Link" Function Is The "Link" Function In AngularJS Directives

By Ben Nadel on

In AngularJS, directives are both powerful and complicated. Understanding them is not a one-time thing; it's a process that requires iteration and experimentation. The documentation is great; but, it will only take you so far. One thing that I wanted to clarify, that I personally find confusing in the documentations, is the fact that the "post link" function and the "link" function are the same thing in AngularJS directives.


 
 
 

 
 
 
 
 

Run this demo in my JavaScript Demos project on GitHub.

In the first half of the Directive documentation, AngularJS makes many references to the linking function. Then, later on, it refers to a linking object that can contain both a pre-link and a post-link function. And, while it explains how the link timing works (in relation to the Document Object Model and the child directives), I feel like the documentation never clearly states that the generic "link function" in the first half is the same as the "post link" function in the latter half.

To demonstrate that this is true, I have created three directives that each use the same link function reference. One configures the directive using the link function; one configures the directive using the link object; and, one configures the directive using nothing but the function reference.

  • <!doctype html>
  • <html ng-app="Demo">
  • <head>
  • <meta charset="utf-8" />
  •  
  • <title>
  • The "Post-Link" Function Is The "Link" Function In AngularJS Directives
  • </title>
  • </head>
  • <body>
  •  
  • <h1>
  • The "Post-Link" Function Is The "Link" Function In AngularJS Directives
  • </h1>
  •  
  • <p
  • bn-using-post-link
  • bn-using-link
  • bn-using-fn-only>
  •  
  • Look at the console-output; I am logging the link-functions from within the
  • AngularJS source-code.
  •  
  • </p>
  •  
  •  
  • <!-- Load scripts. -->
  • <script type="text/javascript" src="./angular-modified-1.3.6.js"></script>
  • <script type="text/javascript">
  •  
  • // Create an application module for our demo.
  • var app = angular.module( "Demo", [] );
  •  
  •  
  • // -------------------------------------------------- //
  • // -------------------------------------------------- //
  •  
  •  
  • // This function will be a shared-link function. In one instance, it will be used
  • // as the only link function; in another instance, it will be used as the "post"
  • // link function in a pre/post linking configuration; and in a final instance, it
  • // will be used as the *only* directive configuration.
  • function sharedLinkFunction( scope, element, attributes ) {
  •  
  • console.log( "Linked, like a boss!" );
  •  
  • }
  •  
  •  
  • // I use the shared-link function as the "post-link" function.
  • app.directive(
  • "bnUsingPostLink",
  • function() {
  •  
  • return({
  • link: {
  • pre: angular.noop,
  • post: sharedLinkFunction
  • },
  • restrict: "A"
  • });
  •  
  • }
  • );
  •  
  •  
  • // I use the shared-link function as the "link" function.
  • app.directive(
  • "bnUsingLink",
  • function() {
  •  
  • return({
  • link: sharedLinkFunction,
  • restrict: "A"
  • });
  •  
  • }
  • );
  •  
  •  
  • // I use the shared-link function as the only directive configuration.
  • app.directive(
  • "bnUsingFnOnly",
  • function() {
  •  
  • return( sharedLinkFunction );
  •  
  • }
  • );
  •  
  • </script>
  •  
  • </body>
  • </html>

What you can't see in this code above is that I have altered the AngularJS source code to log out the Pre and Post linking function references during the compilation phase. Specifically, I have added a console.log statement ot the addLinkFns() function:

  • function addLinkFns(pre, post, attrStart, attrEnd) {
  •  
  • console.log( "addLinkFns[ arguments ]:", arguments );
  •  
  • // ... rest of function here ...
  •  
  • }

As you can infer from the argument names, the first argument is the pre-link function and the second argument is the post-link function. Now, when we run the above code, we get the following console output:


 
 
 

 
 The post-link function is the same as the link function in AngularJS directives. 
 
 
 

As you can see, the shared linking function is always being passed-in as the second argument. This holds true whether we define a "link function" or a "link object" that provides a post-link function. That's because these functions are one-in-the-same. When we use a link "object", the only "new" functionality we get is the pre-link function.




Reader Comments

It might be worth noting that basically the `link` property is just a shorthand for when the `compile` function is empty (which is the majority of times). "Normally", the linking function(s) are specified as the return value of the `compile` function, which can be either a (post-link) function or an object with pre-link and post-link functions registered via `pre` and `post` properties.

From [the docs][1]:

**compile**
[...]
A compile function can have a return value which can be either a function or an object.

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

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

**link**
This property is used only if the compile property is not defined.
[...]

[1]: https://docs.angularjs.org/api/ng/service/$compile#-compile-

Reply to this Comment

@ExpertSystem,

For me, that's one of those head-scratching moments from time to time. Since most directives do *not* require a Compile() function, I will sometimes write this the first time I try to create a compile function:

return({
compile: compile,
link: link,
restrict: "A"
});

.... and then I'm like *why* won't my link function execute?!?! Then, finally, I'm like, "Oh yeah, I gotta return it from the compile function!".

Reply to this Comment

Post A Comment

You — Get Out Of My Dreams, Get Into My Comments
Live in the Now
Oops!
Comment Etiquette: Please do not post spam. Please keep the comments on-topic. Please do not post unrelated questions or large chunks of code. And, above all, please be nice to each other - we're trying to have a good conversation here.