Victor Queiroz

AngularJS: Directives — What They Are and How They Work

What are directives?

Directives (or diretivas in Portuguese) are markers on a DOM element (which can be an attribute, element name, comment, or CSS class) that tell Angular’s HTML compiler ($compile) to attach a designated behavior, or even transform and manage the DOM and its children.

Angular comes with several built-in directives, such as ngView, ngModel, ngBind, ngRepeat, ngShow, and ngHide. Just like you can create your own controllers, you can also create your own directives for use with Angular.

Using directives

Before we write a directive, we need to know how Angular’s HTML compiler determines when to use a given directive.

In the example below, we’re saying that the <input> element corresponds to the ngModel directive:

<input type="text" ng-model="foo">

The following example also corresponds to the ngModel directive:

<input type="text" data-ng:model="foo">

We refer to directives by their normalized name (e.g., ngRepeat, myFirstDirective) in case-sensitive CamelCase. However, since HTML is case-insensitive, directive names need to be denormalized before being used in the DOM.

Denormalization

There are several denormalization processes. One of them is dash-delimited denormalization, which replaces uppercase letters with lowercase letters preceded by a dash (e.g., ngRepeat, ngModel, and myDirective become ng-repeat, ng-model, and my-directive in the DOM). You can also add prefixes and other parameters.

Normalization

The normalization process translates the denormalized name back to the actual directive name:

  1. The x- and data- prefixes are stripped from the element/attribute.
  2. :, -, or _ delimiters are converted to camelCase.

So ng-model, my-directive, or this-is-a-directive are translated to ngModel, myDirective, or thisIsADirective — the reverse of the denormalization process explained above.

Below you can see an example with the possible combinations for the ngBind directive:

<div ng-controller="AppController">
  Hello <input ng-model='name'> <hr/>
  <span ng-bind="name"></span> <br/>
  <span ng:bind="name"></span> <br/>
  <span ng_bind="name"></span> <br/>
  <span data-ng-bind="name"></span> <br/>
  <span x-ng-bind="name"></span> <br/>
</div>

The $compile service supports directives based on element names, attributes, CSS classes, and comments.

Below you can see some methods you can use to declare directives:

<my-dir></my-dir>
<span my-dir="exp"></span>
<!-- directive: my-dir exp -->
<span class="my-dir: exp;"></span>

Binding variables in attributes

Coming soon!

Creating directives

First, let’s talk about the API used to create directives. Just like controllers, directives are registered on modules. To register a directive, you use module.directive.

The module.directive should be used as follows:

angular.module('app', [])

.directive('validate', function() {
  return {
    template: 'This is my first directive, and I am still learning.'
  };
});

The technical definition is module.directive('directiveNormalizedName', directiveFunction) — the function must return an object.

Restricts

Restricts determine how your directives will be invoked. Below is a list of possible restrict values:

  • 'A' — Only match by attribute.
  • 'E' — Only match by element name.
  • 'C' — Only match by CSS class.
angular.module('app', [])

.directive('validate', function() {
  return {
    restrict: 'E',
    template: 'This is my first directive, and I am still learning.'
  };
});

You can also use AEC to make your directive match through all of these methods.

Best practices

This post is still brief on this topic, but I’ll be updating it soon with new tips. I’ll also be increasing my posting frequency.

Cheers, and I look forward to your comments, questions, and feedback!

Comments