Creating a AngularJS Directive

| | 2 min read

We can create directives in AngularJS to bring our own HTML tags or attributes, or even special CSS classes or comments. It is most used for building HTML elements and attributes and rarely used for classes and comments. Using directives we can simplify application's HTML markup and have more organized code.

To illustrate an example, we take a scenario from one of our application Geotagger. It is supposed to have grid of images in one page. That page may have more than one grid and grid will be of same structure and style. Each grid will have a title and each cell in grid will be representing a single item with image and some overlay text. The overlay text will change depending on the state of item it represents. Grid cell will be having progress bar when item is in under process state and title when it is complete.

Here is the proposed HTML structure for a single grid with items rendered using items array.


<div>
  <h2>Grid Title</h1>
  <div>
    <div ng-repeat="item in items" class="item">
      <div>
        <img src="{{item.thumb}}" />
      </div>
      <div ng-if="item.state < 3" class="overlay">
        <progress max="{{item.progress.max}}" value="{{item.progress.value}}"></progress>
      </div>
      <div ng-if="item.state == 3" class="overlay">
        <h3>{{item.title}}</h3>
      </div>
    </div>
  </div>
</div>

Inputs to a single grid are a grid title and items array. So, it is good candidate to have separate HTML element having two special attributes for title and items.

Let us create directive for the grid. Here is how to register a directive for a grid, ready to receive values for two special attributes title and items.


.directive('gtItemGrid', function() {
  return {
    restrict: 'E',
    scope:  {
      items: '=',
      title: '='
    },
    templateUrl: 'directives/item-grid.html'
  };
})

Let us walthrough above lines. The directive name is 'gtItemGrid'. 'gt' is the prefix representing the application 'geotagger'. It is a good practice to use a prefix, otherwise it may conflict with directives provides by some other modules or future HTML elements. Use camelCase for the names. It is returning an object representing the directive from registration callback. 'restrict' property specifies the usage restrictions. We have 'E', which means this directive can only be used as HTML element name. Is is required in our case as we would be using this as an HTML element always. Then we have following scope parameters received from attributes with same name, equal ('=') represents same name.

So, item scope variable could be set using 'item' attribute and title with 'title' attribute. We need to put above HTML into 'directives/item-grid.html' file.

After registering we can use our directive as given below:


<gt-item-grid items="pendingItems" title="'Uploading'"></gt-item-grid>
<gt-item-grid items="completedItems" title="'Completed'"></gt-item-grid>

We will get two grids, provided we have two arrays of items pendingItems and completedItems. Creating directives are easier and it gives more organized code and reusable components.

Please feel free to share your thoughts and doubts regarding this here.