Thursday, 3 December 2015

Create/Learn Custom Directives in AngularJS


Pick up Custom Directives in AngularJS




Introduction:

First of all thank you to all of you for reading this article. I wanted to write technical article from last 2 years but not able to do so. But any way, this is my first technical article.

I have done deep research on custom directives in AngularJS and thought this is the right time to give back to technical community while contributing my bit.

What is Custom Directive in AngularJS?

First of all let me tell you what is directive in AngularJS?

As a high level, directives are indicators on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS's HTML compiler to attach a specified behavior to that DOM element (e.g. via event listeners), or even to transform the DOM element and its children.

“ng-Bind, ng-Model, ng-app, ng-show, ng-if and ng-controller etc are the built in directive in the AngularJS.”

There are so many cases where these built in directives does not fit into the requirement, so angular gives you flexibility to create your own custom directives.

The custom directive gets executed when Angular bootstraps your application, the HTML compiler traverses the DOM matching directives against the DOM elements.

Custom directive should be written in camelCase and then angular will normalize this into different format.

Ex: sampleDirective

This can be written in HTML page like:

 <sample_directive></ sample_directive >

<sample-directive></ sample-directive >

<sample:directive></ sample:directive >

Best Practice: Prefer using the dash-delimited format (e.g. ng-bind for ngBind). If you want to use an HTML validating tool, you can instead use the data-prefixed version (e.g. data-ng-bind for ngBind). The other forms shown above are accepted for legacy reasons but this is advisable to avoid them.

Directive types:

There are four types of directives based on element names, attributes, class names, as well as comments.

Create Custom Directive:

The custom directives are registered on modules. To register a directive, we have to use the module.directive API. module.directive takes the camleCase directive name followed by a factory function. This factory function should return an object with the different options to tell $compile how the directive should behave when matched.

The factory function is invoked only once when the compiler matches the directive for the first time. Any initialization work should be performed here.

Best Practice: In order to avoid collisions with some future standard, it's best to prefix your own directive names. For instance, if you created a <carousel> directive, it would be problematic if HTML7 introduced the same element. A two or three letter prefix (e.g. devCarousel) works well. Similarly, do not prefix your own directives with ng or they might conflict with directives included in a future version of Angular.

Let’s create some example for the custom directive.

I am using Visual studio .Net IDE to work on the example you can use own if required.

Step 1: Open a visual studio and create a new project as web application.

 

Step 2: Select any type of application for this example or choose as per your requirement.


Step 3: Install the latest AngularJS from nugget packages using below screen.


Step 4: Click on Install button for installing the package.


Step 5: After application gets ready, create a new JavaScript file “$\Scripts\CustomDirective.js” for custom directive code.

JavaScript Code:

/// <reference path="angular.js" />


var sampleApp = angular.module("SampleApp", []);


sampleApp.directive('sampleDirective', function () {


    return {

        template: '<div><b>Hi there!! this is a first custom directive!!!!</b></div>',

        restrict: 'E'

    };

});


Step 6: Create new Html page “CustomDirective.html” for html code.

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title>Custom Directive</title>

    <link href="Content/bootstrap.css" rel="stylesheet" />

    <script src="Scripts/angular.min.js"></script>

    <script src="Scripts/CustomDirective.js"></script>  

</head>

<body ng-app="SampleApp">

    <div>       

        <sample-directive></sample-directive>

    </div>


</body>

</html>


Output should be look like below:


Finally your first directive is readyJ

So the restrict option in the above custom directive is E but you can use following other options:

  • 'A' - only matches attribute name
  • 'E' - only matches element name
  • 'C' - only matches class name

These restrictions can all be combined as needed:

  • 'AEC' - matches either attribute or element or class name

When should I use an attribute versus an element? Use an element when you are creating a component that is in control of the template. The common case for this is when you are creating a Domain-Specific Language for parts of your template. Use an attribute when you are decorating an existing element with new functionality.


If the size of the template is too big it is advisable to create a new html file and use “templateUrl” for loading the html code.

Ex:

Change the custom directive code like below:

sampleApp.directive('sampleDirective', function () {


    return {

        templateUrl: 'sampleApp.html,

        restrict: 'E'

    };

});


Now, the time to use the ng-controller in the customer directive. Below is the sample implementation of the directive with controller.

Custom directive with Controller:

JavaScript Code:

/// <reference path="angular.js" />


var sampleApp = angular.module("SampleApp", []);

sampleApp.controller('StudentController', function ($scope) {

    $scope.student = {};

    $scope.student.name = "Abhay Saxena";

    $scope.student.Age = 35;

 });

sampleApp.directive('student', function () {  // this is the another way of writing directive function.

    var directive = {};

      

    directive.restrict = 'E';

    directive.scope = false;

       

    directive.template = "Student: <b>{{student.name}}</b> , Age: <b>{{student.Age}}</b>";


    return directive;   

       

});

HTML Code:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title>Custom Directive</title>

    <link href="Content/bootstrap.css" rel="stylesheet" />

    <script src="Scripts/angular.min.js"></script>

    <script src="Scripts/CustomDirective.js"></script>  

</head>

<body ng-app="SampleApp">

    <div ng-controller="StudentController">

        <student></student>

    </div>


</body>

</html>


Output should look like:



Now, the turn for Isolating the Scope of a Directive:


The above directive is great, but it has a fatal error. We can only use it once within a given scope.

In its current implementation, we'd need to create a different controller each time in order to re-use such a directive. Let’s see the below example.

JavaScript Code:

/// <reference path="angular.js" />


var sampleApp = angular.module("SampleApp", []);



sampleApp.controller('StudentController', function ($scope) {

    $scope.student = {};

    $scope.student.name = "Abhay Saxena";

    $scope.student.Age = 35;

 });


sampleApp.controller('NewStudentController', function ($scope) {

    $scope.student = {};

    $scope.student.name = "Sanjay Saxena";

    $scope.student.Age = 30;

});




sampleApp.directive('student', function () {

    var directive = {};

      

    directive.restrict = 'E';

    directive.scope = false;

       

    directive.template = "Student: <b>{{student.name}}</b> , Age: <b>{{student.Age}}</b>";


    return directive;   

       

});

HTML Code:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title>Custom Directive</title>

    <link href="Content/bootstrap.css" rel="stylesheet" />

    <script src="Scripts/angular.min.js"></script>

    <script src="Scripts/CustomDirective.js"></script>  

</head>

<body ng-app="SampleApp">   

    <div ng-controller="StudentController">

        <student></student>

    </div>

    <div ng-controller="NewStudentController">

        <student></student>

    </div>


</body>

</html>

Output:


So to avoid creating a new controller each time, we need to isolate the scope for the directive implementation.

JavaScript Code:

/// <reference path="angular.js" />


var sampleApp = angular.module("SampleApp", []);


sampleApp.controller('StudentController', ['$scope',function ($scope) {

    $scope.Abhay = { name: 'Abhay Saxena', Age: 35 };

    $scope.Sanjay = { name: 'Sanjay Singh', Age: 38 };

 }])




sampleApp.directive('student', function () {

    var directive = {};

      

    directive.restrict = 'E';

    directive.scope= {studentInfo:'=information'}

       

    directive.template = "Student: <b>{{studentInfo.name}}</b> , Age: <b>{{studentInfo.Age}}</b>";


    return directive;   

       

});


HTML Code:

<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">

<head>

    <title>Custom Directive</title>

    <link href="Content/bootstrap.css" rel="stylesheet" />

    <script src="Scripts/angular.min.js"></script>

    <script src="Scripts/CustomDirective.js"></script>  

</head>

<body ng-app="SampleApp">   

    <div ng-controller="StudentController">

        <student information="Abhay"></student>

        <hr>

        <student information="Sanjay"></student>

    </div>

   


</body>

</html>


Output:


Ref: https://docs.AngularJS.org/guide/directive


No comments:

Post a Comment