Using The This-Binding In Directive Definition Objects In AngularJS
This is a really minor, but I think very interesting point about the directive definition object (DDO) in AngularJS. When you define your directives, you can provide various methods like link() and compile(). When these methods are invoked by the AngularJS framework, they are done so as properties of the DDO. This means that the DDO is the "this" binding during method execution. Which, of course, means that you can use "this" to reference other methods that are also present on the DDO.
Run this demo in my JavaScript Demos project on GitHub.
In the olden-days, if you wanted to gain access to the transclude() function, you needed to put your link() method inside of your compile() method since the compile() method was the way transclude was exposed. However, as of AngularJS 1.2, the transclude() method is made available to the link method itself. This removes the nesting requirement and opens your code structure up to a bit more personal preference.
Of course, if you have a compile() method, you still need to return a link() method (or a link object) from the compile method. And, if you don't want to nest your methods, you can simply reference the link method off of the "this" binding. Not only does this remove the nesting requirement but, it also means that you can add a compile() method later on without having to restructure your code.
To see this in action, I've created a demo that uses both a compile() and a link() method. Both of the methods are members of the directive definition object; and, when the compile() method executes, it simply returns the DDO-based reference to the link method.
<!doctype html>
<html ng-app="Demo">
<head>
<meta charset="utf-8" />
<title>
Using The This-Binding In Directive Definition Objects In AngularJS
</title>
<style type="text/css">
statement {
display: block ;
font-size: 140% ;
}
statement.active {
background-color: gold ;
}
</style>
</head>
<body>
<h1>
Using The This-Binding In Directive Definition Objects In AngularJS
</h1>
<statement>
Kim Smith is a strong woman.
</statement>
<!-- Load scripts. -->
<script type="text/javascript" src="../../vendor/jquery/jquery-2.1.0.min.js"></script>
<script type="text/javascript" src="../../vendor/angularjs/angular-1.4.5.min.js"></script>
<script type="text/javascript">
// Create an application module for our demo.
angular.module( "Demo", [] );
// --------------------------------------------------------------------------- //
// --------------------------------------------------------------------------- //
// I bind to the Statement element and provide some additional behavior.
angular.module( "Demo" ).directive(
"statement",
function statementDirective() {
// Return the directive definition objection.
return({
compile: function( tElement, tAttributes ) {
tElement.html(
tElement.html().replace( /(strong)/g, "$1, powerful" )
);
// NOTE: This works because the methods on the directive
// definition object (DDO) are invoked as properties of the
// DDO. As such, the "this" binding is the DDO object and can
// therefore reference other methods on the DDO (such as link).
return( this.link );
},
link: function( scope, element, attribute ) {
element.hover(
function handleMouseEnter() {
element.addClass( "active" );
},
function handleMouseLeave() {
element.removeClass( "active" );
}
);
},
restrict: "E"
});
}
);
</script>
</body>
</html>
When I run this code and mouse-over the statement, I get the following output:
As you can see, the compile() method augmented the content while the returned link() method added mouse-interaction behaviors.
Again, this is a really minor post and may very well have absolutely no bearing on how you write your AngularJS directives. But, I'm always exciting when I can understand the mechanics of something and think about the ways in which they can be leveraged.
Want to use code from this post? Check out the license.
Reader Comments