Sunday, August 31, 2014

AngularJS for Beginners: Custom Directive: Part I

What is Directive
Directive is a kind of method of AngularJS to create new HTML elements or to add custom functionality to HTML elements. Directives can be considered as markers on a DOM element (attribute, element name, comment or CSS class) which enable compiler of AngularJS to attach a specified behavior to that DOM element or to transform the DOM element and its children. 

Angular comes with a set of built-in directives such as ng-bind, ng-model and ng-view etc. We can also create custom directives of our own.

How to create custom directive
We use Angular module’s directive method to create custom directive. Using the directive method, we can register a new directive by providing the name of directive as string and a function. The name of the directive should always be in camelCase form, and the function we should return an object. Here is a simple example:
 var myModule = angular.module("myModule", []);  
 myModule.controller('BooksController',   
 function BooksController($scope) {  
      $scope.book = {  
           name:'The Tempest',   
           author:'William Shakespeare'  
      };  
 });  
 myModule.directive('myBook', function() {  
      return {  
           template: 'Name: {{book.name}}<br>Author: {{book.author}}'  
      };  
 });  
Here we have created a simple directive that replaces its contents with a static template. We have used the template attribute to do it. We can use that directive in HTML like the following:
 <div ng-controller="BooksController">  
      <div my-book></div>  
 </div>  
In HTML, we have to use the dash-delimited lower-case form of the name of directive. In our case, myBook has to be used as my-book in HTML.

The template and templateUrl Properties
The HTML template can grow bigger. It is difficult to maintain larger HTML template inside a single JavaScript string. We can put the HTML template in a separate file and make AngularJS load it from the file. We can do it by using the templateUrl property. Here is an example:
 var myModule = angular.module("myModule", []);   
 myModule.controller('BooksController',    
 function BooksController($scope) {   
      $scope.book = {   
           name:'The Tempest',    
           author:'William Shakespeare'   
      };   
 });   
 myModule.directive('myBook', function() {   
      return {   
           templateUrl: 'my-template.html'   
      };   
 });  
AngularJS will load the HTML template from the URL provided in the templateUrl property. Here, my-template.html page will contain the code like:
 Name: {{book.name}}<br>Author: {{book.author}}  
Unless our template is very small, it is best practice to keep the HTML template in a separate HTML file and load it using the templateUrl property.

Properties of Directive
We can use several properties to define a custom directive. The other most commonly used properties are:
  • restrict
  • scope
  • template
  • templateUrl
  • link
We have already discussed about template and templateUrl properties. We will discuss scope and link in the next post. Now, let's know about the restrict property.
The restrict property determines how the directive will be activated or triggered. There are 4 types of restrict properties:
  • 'A' - matches attribute name
  • 'E' - matches element name
  • 'C' - matches CSS class name
  • 'M' - matches comment name
Several restrictions can be used simultaneously by using them in combined form:
'AEC' - matches either attribute or element or class name

Let's apply restrict property to our directive and change to match by element name:
 var myModule = angular.module("myModule", []);   
 myModule.controller('BooksController',    
 function BooksController($scope) {   
      $scope.book = {   
           name:'The Tempest',    
           author:'William Shakespeare'   
      };   
 });   
 myModule.directive('myBook', function() {   
      return {  
           restrict: 'E',   
           templateUrl: 'my-template.html'   
      };   
 });  
We have to use that directive in HTML now by using tag name <my-book> like the following:
 <div ng-controller="BooksController">   
      <my-book></my-book>   
 </div>