Communicate Between Controllers

Creating Custom Directives in AngularJS

Directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS’s HTML compiler ($compile) to attach a specified behavior to that DOM element (e.g. via event listeners), or even to transform the DOM element and its children.

AngularJS.org

In this blog, I will show how to create custom directives. To better understand concept of Directive please go through the AngularJS’s Custom Directive section. If you are new to AngularJS, please read my first blog on Introduction of AngularJS.

What are Directives?

Angular comes with a set of in-built directives such as ngBind, ngIf, ngShow, ngModel, etc… We can also create our own directives the same way we create controllers & services.

Directive Types

There are mainly two type of directives:

  1. Element Directive
  2. Attribute Directive

Element Directive

To call the Element Directive in html page, we need to call it like an html elements such as: div or header etc…

<my-element-directive></my-element-directive>

Attribute Directive

To call the Attribute Directive in html page, we need to call it like an html attributes such as: id, class or data etc…

<div my-attribute-directive></div>

Create Custom Directive

To create custom directive we need to use module.directive API. This module.directive takes two parameters: 1) name & 2) function. This function will return an object which informs AngularJS’s compiler, how to behave when this directive called.

var app = angular.module("customDirectiveSample", []);

// Element Directive
app.directive("myElementDirective", function(){
    return {
        restrict: "E"      // E stands for 'Element'
    }
});

// Attribute Directive
app.directive("myAttributeDirective", function(){
    return {
        restrict: "A"      // A stands for 'Attribute'
    }
});

Properties

Let’s say we have some information that is repeated many time in our project and in case of any change in it we need to do it several times. In this case it is advisable to use template to make it easy to maintainable. Below is the code showing template property in Attribute directive.

var app = angular.module("customDirectiveSample", []);

app.controller("myController", function(){
    $scope.person = {
        name: "Devansh",
        surname: "Panchal"
    }
});

// Attribute Directive
app.directive("myAttributeDirective", function(){
    return {
        restrict: "A",      // A stands for 'Attribute'
        template: "Name: {{person.name}} and Surname: {{person.surname}}"
    }
});
<div ng-controller="myController">
    <div my-attribute-directive></div>
</div>
Name: Devansh and Surename: Panchal

We can have ngController and $scope inside our directive as property. Instead of writing content in directive we can exclude the content in .html file and include it in the directive as template.

var app = angular.module("customDirectiveSample", []);

// Element Directive
app.directive("myElementDirective", function(){
    return {
        restrict: "E",      // E stands for 'Element'
        templateUrl: "my-file.html",
        controller: function($scope){
            $scope.person = {
                name: "Devansh",
                surname: "Panchal"
            };
        }
    }
});
<my-element-directive></my-element-directive>
Name: {{person.name}} and Surname: {{person.surname}}
Name: Devansh and Surename: Panchal

Manipulate DOM with Directive

To manipulate DOM with directive, we can use link function. We can declare like as:

function link(scope, element, attrs) {
   ...
}
  • scope is an Angular scope object.
  • element is the jqLite-wrapped element that this directive matches.
  • attrs is a hash object with key-value pairs of normalized attribute names and their corresponding attribute values.

To understand how link function works; let’s have an example where we need to remove the rotator .gif image once the main image is loaded.

<div class="resp-image">
    <img imageLoaded src="path/to/image.jpg" alt="Main Image" title="Main Image" />
.resp-image {
    background: url(path/to/rotator.gif) 50% 50% no-repeat;
}
app.directive('imageLoaded', function() {
  return {

    restrict: 'A',

    link: function(scope, element, attrs) {
      element.on('load', function() {
        $('.resp-image').css('background','none');
      });
    }

  };
});

I have used imageLoaded as an Attribute directive and used it on <img /> tag. So when the image gets loaded in the DOM it will fire the load event which we have caught in link function.

So whenever we have used this imageLoaded attribute directive, it will remove the rotator image once the actual image loaded.

Note:

It is advisable to use controller when you want to expose an API to other directives. Otherwise use link.

Web/ UI & Front-end developer based in Ahmedabad, GJ, India. Here to help/ discuss community to spread web awareness.

Leave a reply:

Your email address will not be published.