AngularJS Directives

A directive is a way to create HTML-like tags and attributes that are inserted into templates. By providing directives, you can easily display your own output as tags and extend AngularJS.

Directive Basics and Creation

AngularJS assigns special features inside HTML by adding its own attributes to HTML tags or by creating tags. These features are called directives.

Directives are not only provided by AngularJS; you can also create them yourself. By writing your own directives, you can add your own tags.

Directives are created in a module by using the directive method provided by the module object.

module.directive(name, function);

The first argument specifies the directive name. This name can be used as the tag name or attribute name. The second argument specifies a function object that performs the directive’s actual processing.

The directive method is simple to use. The key question is how to create the function passed as the argument. Think of it as processing that returns an object containing the values needed by the directive.

The simplest form returns an object with a template value.

function() {
    return {template: ... output content ...};
}

template is the template for the output tag. In other words, the content prepared here is displayed directly on the web page.

Creating a Simple Directive

Let us create a simple directive that outputs OK!. Save the following script as script.js.

var myapp = angular.module('myapp',[]);

myapp.directive('ok', function(){
    return {
        template:'<span style="font-size:24pt;color:red;">OK!</span>'
    };
});

Here, the first argument of directive is ok. The second argument is a function that only returns {template: ...}. Once you understand the basic directive structure, you can see that this is not difficult.

Use it from HTML as follows.

<!DOCTYPE html>
<html>
<head>
    <title>AngularJS Sample</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
    <script src="script.js"></script>
</head>
<body ng-app="myapp">
    <h1>Directive</h1>
    <ok></ok>
</body>
</html>

When this page is opened, OK! is shown in red. The custom <ok></ok> tag is converted into a normal HTML tag like the following.

<span style="font-size:24pt;color:red;">OK!</span>

With directives, you can display complex output through simple custom tags.

Manipulating Directive Elements

The previous example is enough for a very simple directive, but ordinary HTML tags often have values between start and end tags or attributes on the tag. Directives can also handle those cases.

Instead of returning a simple object, return a function object.

function() {
    return function(scope, element, attrs) {
        ... required processing ...
    };
}

The returned function receives three arguments.

  • scope: The scope object.
  • element: The DOM element of this directive.
  • attrs: An object that handles attribute information.

Use element and attrs to obtain text inside a directive tag or attributes included in the tag.

Writing the Directive

Modify script.js so that it uses attributes and the text inside the tag.

var myapp = angular.module('myapp',[]);
 
myapp.directive('ok', function(){
    return function(scope,element,attrs){
        var size = attrs['size'];
        size = size == null ? '24pt' : size;
        var color = attrs['color'];
        color = color == null ? 'red' : color;
        var txt = element[0].textContent;
        var tag = '<span style="font-size:' + size  + ';color:' + color + ';">' + txt + '</span>';
        element[0].innerHTML = tag;
    };
});

The size and color attributes are obtained from attrs. If the attributes are not included in the tag, the values are undefined, so default values are assigned.

Text inside a tag such as <ok>Hello</ok> can be obtained with:

var txt = element[0].textContent;

Then assign the generated tag text to element[0].innerHTML to replace the contents of the <ok> tag.

Integrating the Directive into HTML

Use the new directive as follows.

<ok>This is sample!</ok>
<hr>
<ok size="36pt">This is size sample!</ok>
<hr>
<ok color="blue">This is color sample!</ok>
<hr>
<ok color="green" size="48pt">This is full sample!</ok>

If size or color is not specified, the defaults are 24pt and red. All text written inside each tag is displayed as-is. This creates an <ok> tag that can easily set text color and size.

Setting Events in Directives

Directives can do more than customize display. You can bind events to tags and create interactive directives.

The element argument passed to the directive is a DOM element, so you can assign functions to event properties or call addEventListener.

var myapp = angular.module('myapp',[]);
 
myapp.directive('click', function(){
    return function(scope, element, attrs){
        element[0].addEventListener("click", function(){
            var txt = this.textContent;
            alert('you click "' + txt + '"!');
        }, false);
    };
});

This creates a <click> directive that shows an alert when clicked.

<click>This is click sample!</click>

Clicking the text displays an alert. Event registration is the same as normal DOM event handling.

Creating Attribute Directives

You can create directives not only as whole tags but also as attributes. Attribute directives can be added to many different HTML tags.

module.directive(name, 
    function() {
        return {
        restrict: 'A',
        template: outputContent
        };
    });

The returned object specifies restrict in addition to template. This indicates where the directive can be used.

  • E: Can be used as an element, such as <ok>.
  • A: Can be used as an attribute, such as <p ok>.
  • AE: Can be used in both ways.

Specifying restrict:'A' creates a directive that is used as an attribute.

myapp.directive('ok', function(){
    return {
        restrict: 'A',
        template:function(scope, element){
            var size = 24;
            switch(element['ok']){
            case 'large':
                size = 48; break;
            case 'midium':
                size = 36; break;
            case 'small':
                size = 24; break;
            }
            var tag ='<span style="font-size:' + size
                + 'pt">' + scope[0].textContent
                + '</span>';
            return tag;
        }
    };
});

It can be used like this.

<div ok="large">This is Large sample!</div>
<div ok="midium">This is Midium sample!</div>
<div ok="small">This is Small sample!</div>

When specifying a function for template, scope and element are passed as arguments. Attribute values can be obtained from element, such as element['ok'], while the tag text can be obtained from scope[0].textContent.

Attribute directives are best designed as additions to the main tag. If you want to replace the entire tag boldly, it is usually better to create an element directive.