Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
AngularJS Web application development Cookbook

You're reading from   AngularJS Web application development Cookbook Over 90 hands-on recipes to architect performant applications and implement best practices in AngularJS

Arrow left icon
Product type Paperback
Published in Dec 2014
Publisher Packt
ISBN-13 9781783283354
Length 346 pages
Edition 1st Edition
Arrow right icon
Author (1):
Arrow left icon
Matthew Frisbie Matthew Frisbie
Author Profile Icon Matthew Frisbie
Matthew Frisbie
Arrow right icon
View More author details
Toc

Table of Contents (12) Chapters Close

Preface 1. Maximizing AngularJS Directives 2. Expanding Your Toolkit with Filters and Service Types FREE CHAPTER 3. AngularJS Animations 4. Sculpting and Organizing your Application 5. Working with the Scope and Model 6. Testing in AngularJS 7. Screaming Fast AngularJS 8. Promises 9. What's New in AngularJS 1.3 10. AngularJS Hacks Index

Working through the directive spectrum

Directives can be incorporated into HTML in several different ways. Depending on how this incorporation is done, the way the directive will interact with the DOM will change.

How to do it…

All directives are able to define a link function, which defines how that particular directive instance will interact with the part of the DOM it is attached to. The link functions have three parameters by default: the directive scope (which you will learn more about later), the relevant DOM element, and the element's attributes as key-value pairs.

A directive can exist in a template in four different ways: as an HTML pseudo-element, as an HTML element attribute, as a class, and as a comment.

The element directive

The element directive takes the form of an HTML tag. As with any HTML tag, it can wrap content, have attributes, and live inside other HTML elements.

The directive can be used in a template in the following fashion:

(index.html)

<div ng-app="myApp">
  <element-directive some-attr="myvalue">
    <!-- directive's HTML contents -->
  </element-directive>
</div>

This will result in the directive template replacing the wrapped contents of the <element-directive> tag with the template. This element directive can be defined as follows:

(app.js)

angular.module('myApp', [])
.directive('elementDirective', function ($log) {
  return {
    restrict: 'E',
    template: '<p>Ze template!</p>',
    link: function(scope, el, attrs) {
      $log.log(el.html());
      // <p>Ze template!</p>
      $log.log(attrs.someAttr);
      // myvalue
    }
  };
});

Note that for both the tag string and the attribute string, AngularJS will match the CamelCase for elementDirective and someAttr to their hyphenated element-directive and some-attr counterparts in the markup.

If you want to replace the directive tag entirely with the content instead, the directive will be defined as follows:

(index.html)

angular.module('myApp', [])
.directive('elementDirective', function ($log) {
  return {
    restrict: 'E',
    replace: true,
    template: '<p>Ze template!</p>',
    link: function(scope, el, attrs) {
      $log.log(el.html());
      // Ze template!
      $log.log(attrs.someAttr);
      // myvalue
    }
  };
});

This approach will operate in an identical fashion, but the directive's inner HTML will not be wrapped with <element-directive> tags in the compiled HTML. Also, note that the logged template is missing its <p></p> tags that have become the root directive element as they are the top-level tags inside the template.

The attribute directive

Attribute directives are the most commonly used form of directives, and for good reason. They have the following advantages:

  • They can be added to existing HTML as standalone attributes, which is especially convenient if the directive's purpose doesn't require you to break up an existing template into fragments
  • It is possible to add an unlimited amount of attribute directives to an HTML element, which is obviously not possible with an element directive
  • Attribute directives attached to the same HTML element are able to communicate with each other (refer to the Interaction between nested directives recipe)

This directive can be used in a template in the following fashion:

(index.html)

<div ng-app="myApp">
  <div attribute-directive="aval" 
     some-attr="myvalue">
  </div>
</div>

Tip

A nonstandard element's attributes need the data- prefix to be compliant with the HTML5 specification. That being said, pretty much every modern browser will have no problem if you leave it out.

The attribute directive can be defined as follows:

(app.js)

angular.module('myApp', [])
.directive('attributeDirective', function ($log) {
  return {
    // restrict defaults to A
    restrict: 'A', 
    template: '<p>An attribute directive</p>',
    link: function(scope, el, attrs) {
      $log.log(el.html());
      // <p>An attribute directive</p>
      $log.log(attrs.attributeDirective);
      // aval
      $log.log(attrs.someAttr);
      // myvalue
    }
  };
});

Other than its form in the HTML template, the attribute directive functions in pretty much the same way as an element directive. It assumes its attribute values from the container element's attributes, including the attribute directive and other directives (whether or not they are assigned a value).

The class directive

Class directives are not altogether that different from attribute directives. They provide the ability to have multiple directive assignments, unrestricted local attribute value access, and local directive communication.

This directive can be used in a template in the following fashion:

(index.html)

<div ng-app="myApp">
  <div class="class-directive: cval; normal-class" 
       some-attr="myvalue">
  </div>
</div>

This attribute directive can be defined as follows:

(app.js)

angular.module('myApp', [])
.directive('classDirective', function ($log) {
  return {
    restrict: 'C',
    template: '<p>A class directive</p>',
    link: function(scope, el, attrs) {
      $log.log(el.html());
      // <p>A class directive</p>
      $log.log(el.hasClass('normal-class'));
      // true
      $log.log(attrs.classDirective);
      // cval
      $log.log(attrs.someAttr);
      // myvalue
    }
  };
});

It's possible to reuse class directives and assign CSS styling to them, as AngularJS leaves them alone when compiling the directive. Additionally, a value can be directly applied to the directive class name attribute by passing it in the CSS string.

The comment directive

Comment directives are the runt of the group. You will very infrequently find their use necessary, but it's useful to know that they are available in your application.

This directive can be used in a template in the following fashion:

(index.html)

<div ng-app="myApp">
  <!-- directive: comment-directive val1 val2 val3 -->
</div>

The comment directive can be defined as follows:

(app.js)

angular.module('myApp', [])
.directive('commentDirective', function ($log) {
  return {
    restrict: 'M',
    // without replace: true, the template cannot
    // be inserted into the DOM 
    replace: true,
    template: '<p>A comment directive</p>',
    link: function(scope, el, attrs) {
      $log.log(el.html()) 
      // <p>A comment directive</p>
      $log.log(attrs.commentDirective) 
      // 'val1 val2 val3'
    }
  };
});

Formerly, the primary use of comment directives was to handle scenarios where the DOM API made it difficult to create directives with multiple siblings. Since the release of AngularJS 1.2 and the inclusion of ng-repeat-start and ng-repeat-end, comment directives are considered an inferior solution to this problem, and therefore, they have largely been relegated to obscurity. Nevertheless, they can still be employed effectively.

How it works…

AngularJS actively compiles the template, searching for matches to defined directives. It's possible to chain directive forms together within the same definition. The mydir directive with restrict: 'EACM' can appear as follows:

<mydir></mydir>

<div mydir></div>

<div class="mydir"></dir>

<!-- directive: mydir -->

There's more…

The $log.log() statements in this recipe should have given you some insight into the extraordinary use that directives can have in your application.

See also

  • The Interaction between nested directives recipe demonstrates how to allow directives attached to the same element to communicate with each other
lock icon The rest of the chapter is locked
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime