Angularjs

Angular JS Custom Directives


Angular JS Custom Directives

Apart from using angular’s built in directives to manipulate the DOM we can define our own directives.Once the web page is compiled the DOM for the web page is built then angular will start parsing the DOM and when it finds the matching directive name on any element or attribute it will execute the directive and the content of it will be rendered to the web page.

Directives should be registered with the application module like other controllers and service functions through directive function.The first parameter to the directive() function is a directive name.This is what used in HTML to activate the directive. The second parameter is a Javascript function that returns a Javascript object which defines behavior and template code.

NOTE: “camelCase” naming convention is followed for directive names.

syntax

angular.module("myApp",[]).directive("myDirective",function($scope){
});

There are four ways of implementing directives:

  • Element directives
  • Attribute directives
  • CSS class directives
  • Comment directives

Apparently, out of all these types, angular recommends to use element and attribute directives and leave the CSS and comment directives.

The directive type determines how the directive should be activated.An element type is activated when it encounters an HTML element that matches a directive name.An attribute type is activated when it encounters an HTML attribute that matches a directive name.A CSS type is activated when it encounters a class with the directive name.And, a comment type is activated when it encounters a matching comment name in HML.

syntax

<!-- Element type -->
<my-directive></my-directive>

<!--Attribute type-->
<div my-directive></div>

<!-- Class type -->
<div class="my-directive"></div>

<!-- Comment type -->
<!-- directive:my-directive -->

 

A Basic Directive

var app = angular.module("myapp",[])
app.directive("myDirective" , function(){
return{
restrict : 'EA',  /*restrict the directive to element and attributes*/
template : '<p> Custom directive for Element and Attribute types:{{testData}}</p>'
}
});
app.controller("myController",['$scope',function($scope){
$scope.testData = "Hello!!!";
}];

Here “myDirective” is our directives name that is used by angular while parsing the DOM.Since we are restricting it to an element and attribute types it will execute and render when it encounter an element or attribute with “my-directive” name.

The code defined with the template property will be rendered into the HTML page.If we have a complex code it is recommended to place the code in a separate file and use it in a directive using templateUrl property.

 

Isolating the $scope from directive

By default, the directive is said to be bound hard to the parent $scope of the controller.This makes it difficult to reuse the directive to only once within the same controller.Since $scope variables have same values within the same controller.If we modify the $scope variables in the controller then the directive behavior is going to be changed accordingly.

For Example,

var app = angular.module("myapp",[])
app.directive("myDirective" , function(){
return{
restrict : 'EA',  /*restrict the directive to element and attributes*/
template : '<p> Inherited scope variables :{{message}}</p>'
}
});
app.controller("myController",['$scope',function($scope){
$scope.message= "Hello!!!";
}];

Here we are using controller’s $scope variable in directives template.It restricts the reuse of directive in the view since the directive is associated with the controller data with parent $scope.

To avoid this we have to isolate the scope from parent scope of the controller.This can be done by defining a scope property of the directive which is a Javascript object.

We define it as below:

var app = angular.module("myapp",[])
app.directive("myDirective" , function(){
return{
restrict : 'EA',  /*restrict the directive to element and attributes*/
scope : {},
template : '<p> Custom directive for Element and Attribute types:{{testData}}</p>'
}
});
app.controller("myController",['$scope',function($scope){
$scope.testData = "Hello!!!";
}]);

 

<!DOCTYPE html>
<html>
<head>
<title>Isolated scope examples</title>
</head>
<body ng-app="myapp" ng-controller="myController">
<my-directive></my-directive>
</body>
</html>

 

Here the directive’s template is rendered into HTML with only “Custom directive for Element and Attribute types:” text and the expression {{testData}} evaluates to null. Since we isolated the directive’s scope it will not be able to communicate with the outside world.

Try It!

Now the question is how to bound the directive with the HTML.This can be achieved using angular’s local scope properties.Angular has three such properties as below:

  1. “@”
  2. “=”
  3. “&”

‘@’ local scope property:

This is used to access the string variables from other components of the application.Any change in variables will be reflected within the directive but vice versa is not possible.This is also called as one-way data binding.

app.js

var app = angular.module("myapp",[])
app.directive("myDirective" , function(){
return{
restrict : 'EA', /*restrict the directive to element and attributes*/
scope : {
message : "@"
},
template : '<p> Custom directive for Element and Attribute types:{{message}}</p>'
}
});
app.controller("myController",['$scope',function($scope){
$scope.testData = "Hello!!!";
}];

Here testData is bound with the directive using local scope property @.And, directives scope name is used to bind with the directive.

index.html

<body ng-app="myapp" ng-controller="myController">
<my-directive message="{{testData}}"></my-directive>
</body>

Try It!

 

‘=’ local scope property

This is used for two-way data binding, unlike ‘@’  local scope property.Let’s see an example.

app.js

var app = angular.module("myapp",[])
app.directive("myDirective" , function(){
   return{
       restrict : 'EA',  /*restrict the directive to element and attributes*/
       scope : {
       message: '=scopeName'
       },
       template : '<p> Custom directive for Element and Attribute types:{{message.name}}</p>'
    }
});
app.controller("myController",['$scope',function($scope){
   $scope.testData = {
        name:"AASHISH",
        age:24
     };
   }]);

index.html

<my-directive scope-name="testData"></my-directive>

Here the attribute name mentioned after the “=” sign is used to communicate with the view and this should be applied as an attribute in the view and isolated scope variable ‘message’ is used in the directive.

Attributes value should be direct model value unlike an expression used with ‘@’ prefix.

Try It!

 

‘&’ local scope property

This is also called as method binding property.This is used especially whenever directive needs to use callback back function that is defined in the controller.

app.js

var app = angular.module("myapp",[])
app.directive("myDirective" , function(){
 return{
 restrict : 'EA', /*restrict the directive to element and attributes*/
 scope : {
 name: '&'
 },
 template : `<p> Custom directive for Element and Attribute types:
 Method binding example 
 <input type="button" value="GetName" ng-click="name()"/>
 </p>`
 }
});
app.controller("myController",['$scope',function($scope){
 $scope.testData = {
 name:"AASHISH",
 age:24
 };
 $scope.name1 = "Ram";
 $scope.getName = function(){
 $scope.name1=$scope.testData.name;
 }
 }]);

index.html

<body ng-app="myapp" ng-controller="myController">
<my-directive name="getName()"></my-directive>
{{name1}}
</body>

Here we are binding the controllers getName() method with the directive using ‘&’ prefix.The scope variable used in the directive is used as an attribute in view and its value should be the method in the controller.

Try It!

Leave a Reply

Your email address will not be published. Required fields are marked *