AngularJs Directives

What are Directives?

Directives may be the most difficult part of AngularJs and at the same time the most powerful and useful. Think of directives as components you use to assemble an application. You can create your own HTML tags or attributes. Angular comes with a lot of them already included. Thinks like ng-repeat ng-show... are nothing else than directives.

When to use Directives

Use them as often as you can. Not only are directives reusable but they also keep your application code clean, structured and readable.


Directive Definition Object

Lets take a look at the Directive Definition Object and the things that can be configured. The structure of a angularjs directive looks like the following.

app.directive('myDirective', function() {  
  return {
    restrict: ...,
    controller: ...,
    priority: ...,
    require: ...,
    terminal: ...,
    scope: ...,
    template: ...,
    templateUrl: ...,
    replace: ...,
    transclude: ...,
    compile: ...,
    link: ...
  };
});

restrict

defines how you want to use your directive. Is it a Tag, an Attribute, a Class or a Comment?

<!-- E - Element name: -->  
<my-directive></my-directive>  
<!-- A - Attribute (default) -->  
<div my-directive="exp"></div>  
</div> <!-- C - Class -->  
<div class="my-directive: exp;">  
<!-- M - Comment -->  
<!-- directive: my-directive exp -->  
'A' - <span ng-sparkline></span>  
'E' - <ng-sparkline></ng-sparkline>  
'C' - <span class="ng-sparkline"></span>  
'M' - <!-- directive: ng-sparkline -->  

controller

Setting this option creates a controller for the directive. It is a normal controller so you can inject services or create methods that the directive needs.

controller: function($scope, $element, $attrs, $transclude, ...) { ... },  

priority

When there are multiple directives on a HTML element, with the priority option it is possible to configure an order in which they are compiled.

priority: 0,  

require

Require another directive and inject its controller as the fourth argument to the linking function. The require takes a string name (or array of strings) of the directive(s) to pass in.

 require: 'siblingDirectiveName',

terminal

Sometimes it’s useful to stop the execution of the compiler for including other directives. This is most useful when used in conjunction with setting the priority. terminal will stop the execution of any directives at a lower priority than this one.

terminal: false,  

scope

Directives can be given their own scope. This is very import to make them independent from outside.

scope: {  
         location: '@'        
      },

template

Replaces the current element (or content) with the specified HTML.

template: '<div></div>',  

templateUrl

Most of the time its better to serve a sepperate HTML file instead of a template String in the directive.

templateUrl: 'partials/custom/directive/mydirective.tmpl.html',  

replace

Specifies if the element itself (true) or the content (false) of the element will be replaced.

replace: false,  

transclude

If this is set to true it basically means that you can bring your own content. Take for example the ng-repeat. It will repeat the content of the transclude element. So you fill the directive with your own content.

transclude: false,  

compile

The compile function deals with transforming the template DOM. This is rarely used since most of the directives do not do template transformation.

compile: function compile(tElement, tAttrs, transclude) {  
        return {
          pre: function preLink(scope, iElement, iAttrs, controller) { ... },
          post: function postLink(scope, iElement, iAttrs, controller) { ... }
        }
},

This property is used only if the compile property is not defined. The link function is responsible for registering DOM listeners as well as updating the DOM. It is executed after the template has been cloned. This is where most of the directive logic will be put.

link: function (scope, element, attrs) {  
},

Examples

We use these properties:

  • restrict: We want this to be an attribute.
  • scope: We bind the attribute 'location' to the equivalent name in our scope.
  • template: Our HTML template.
app.directive('explWelcome', function() {  
  return {
    restrict: 'A',
    scope: {
         location: '@'        
      },
    template: '<div>Weather for {{location}}</div>'
  }
});
<div expl-Welcome location="Vienna"></div>  

jsfiddle


We use these properties:

  • restrict: We want this to be an attribute.
  • template: Our HTML template.
  • link: In the link function we do most of the logic of directives. We get 3 parameters here. 'scope' is our directive's scope. 'element' is the jqLite-wrapped element that this directive matches. 'attrs' is a key-value object with the attribute names and values.
app.directive('explWelcome', function () {  
    return {
        restrict: 'A',
        template: '<div>Hello {{location}}</div><input ng-model="location"><input ng-model="color">',
        link: function (scope, element, attrs) {
            scope.color = attrs.color;
            scope.location = attrs.location;
            scope.$watch('color', function (color) {
                element.css('color', color);
            });
        }
    };
});
<div expl-Welcome location="Max" color="BLUE" />  

jsfiddle


Thomas Sattlecker

Thomas Sattlecker

View Comments
Navigation