Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Javascript

Reusable Components using Angular’s Directives

4.75/5 (3 votes)
29 May 2016CPOL8 min read 26.2K  
Learn about Custom Directives as reusable components in AngularJS

Introduction

Angular is a client-side JavaScript framework for writing dynamic web applications. It's built and maintained by Google. We can choose either an MVC (Model-View-Controller) or MVVM (Model-View-ViewModel) approach. These approaches give us flexibility over design patterns when developing applications.

Angular is a structural framework for enhancing HTML. It simply brings concepts from various programming languages, both JavaScript and server-side languages and makes HTML the dynamic language too. This means that we get an approach to developing applications without needing to refresh models, update the DOM and other time-consuming tasks such as browser bug fixes and inconsistencies.

Importance of AngularJS

There are many JavaScript frameworks available apart from AngularJS. But there are some features which make Angular more popular than other frameworks. Some of the features of AngularJS are:

  • MVC and MVVM

    Angular follows structured MVC or MVVM approaches. This means, the data lives in a Model, the HTML lives as a template to be rendered as a View, and we use a Controller to connect the two. Controller drives the Model and View value changes.

    The difference between MVC and MVVM, is that MVVM is specifically targeted at user interface development. The view consists of the presentation layer, the ViewModel contains the presentation logic and the Model contains the business logic and data. MVVM was designed to make two-way binding easier.

  • Two-way data-binding

    Two-way binding is a concept which provides synchronization between Model and View layers. Changes to either of them reflects in the other one.

    The way we bind these values is through Angular expressions. We can also bind Models using an attribute called ng-model.

  • Dependency Injection (DI)

    Dependency Injection is a software design pattern that deals with how components get hold of their dependencies. An injection is the passing of a dependency to a dependent Object, these dependencies are often referred to as Services.

    In AngularJS, we use the arguments of a function to declare the dependencies we want, and Angular gives them to us. If we forget to pass in a dependency but reference it where we expect it, the service will be undefined and result in a compile error inside Angular.

  • Single Page Applications (SPAs)

    One of the key features of Angular is, it supports Single Page Application development. In an SPA, all necessary code (HTML, CSS, JavaScript) is retrieved with a single page load. The page does not reload in the process. And it does not transfer the control to another page. Data and partial pages are updated through Ajax calls.

First Look into Angular

Before discussing the reusable aspects of Angular, let us setup the environment for angular app development and understand the basic concepts like module, controller and so on.

Environment Setup

Download AngularJS library to be used in web application development from the official website (https://angularjs.org/). Angular library consists of a single JavaScript file, angular.js. Download will provide the debug version and minified version of the file. Use the minified version for production deployment.

Include the library into the page using Script tag (<script>).

HTML
<script src = "<Library path>"></script>

(Or)

Use include path of Google CDN (content delivery Network) or any other official content sharing websites.

HTML
<script src="<a href="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.2/angular.min.js">https://ajax.googleapis.com/ajax/libs/angularjs/1.5.2/angular.min.js</a>" />

Modules & Controller

Modules

  • Module in AngularJS defines an application. A module is a container for different parts of an application. A module is created by using the AngularJS function angular.module.
JavaScript
var app = angular.module("myApp", []);

The "myApp" parameter refers to an HTML element in which the application will run. We can have multiple modules in a single application. Second parameter defines the dependency modules or the built-in or custom modules used by our module.

Controllers

As the name specifies, AngularJS controllers control the data and process of AngularJS applications. Controllers are where we define our app’s behavior by defining functions and values. The ng-controller directive defines the application controller.

JavaScript
app.controller ("MyController", function ($scope) {

      $scope.message = "Hello, I am controller!";

});

We have used $scope here. Scope holds the model data that we need to pass to the view. It uses two-way data binding mechanism to bind model data to view.

We can define the controllers in separate functions too.

JavaScript
angular
   .module("app.config")
   .controller('configcontroller', configcontroller);

function configcontroller($scope, configservice) {
     //some code
}

First App

Angular applications will have the views defined in html and controller will be defined in JavaScript file. Let us look into the structure of an Angular app using a sample application.

Sample application view is defined as follows.

Index.html
HTML
<html>
      <head>
            <title> My FirstApp </title>
            <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.2/angular.min.js"></script>
            <script src = "app.js" type = "text/javascript"></script>​​​​​​
      </head>
      <body>
            <div ng-app ="myApp" ng-controller ="MyController">
                     <h1> {{message}} </h1>​​​​​​
            </div>
      </body>
</html>

Sample controller, defined below will assign a message to the scope variable, which gets displayed in the view defined earlier. Both files are linked to each other using the script reference in view. Module and controller name references are in both view and controller files.

app.js
JavaScript
var app = angular.module("myApp", []);
app.controller ("MyController", function ($scope) {
                        $scope.message = "Hello, I am controller!";
            });

Run the application and observe the message display in browser.

Image 1

Directives

Directives are markers on DOM elements (such as elements, attributes, css, and more). These can be used to create custom HTML tags that serve as new, custom widgets. Directives allow you to extend the existing HTML with your own elements or attributes and to add behavior to existing elements or attributes.

There are many built-in directives we use as part of angular app. Similarly, we can create our own custom directives to define the reusable component.

Some of the built-in directives, which we discussed earlier are ng-app and ng-model.

  • The ng-app directive initializes an AngularJS application.
  • The ng-model directive binds the value of HTML controls (input, select, textarea) to application data.

Consider the below example explaining the ng-model directive. Input tag value is bind to the variable ‘yourName; using the ng-model directive and the same is displayed using angular expression.

HTML
<div ng-app="myApp">
            <p> Name: <input type="text" ng-model="yourName"> </p>
            <p> Name: {{yourName}} </p>
</div>

Here, the ng-app directive tells AngularJS that the <div> element is the owner of the AngularJS application. Run the application and observe the behavior, where the data entry in the text box will get displayed immediately on the screen.

Custom Directives

Although AngularJS provides wide range of directives, we will often need to create application specific directives. We can create three types of directives - class, attribute and element. Depends on the component usage and applicability, select an appropriate type of directive. Also, we can define a directive as multiple types, that is the same directive can be used as an attribute and element/class.

Directive Configurations

Before moving to the custom directive development, let us understand the different configuration options available.

  • Restrict - Using restrict, you can restrict the directive to A (attribute), E (element), and C (class). By default, directives are restricted to attributes.
  • Template - Appends a given HTML as the child element of the element
  • TemplateUrl - A URL for a given template that would be loaded and appended to the element
  • Replace - If set to true will replace the entire element with a given template (used with the template or templateUrl configurations)
  • Link - A function that receives the scope, directive element, the element attributes as parameters and controllers. The function should be used to add event listeners or to manipulate the DOM

Types of Custom Directives

  • Class Directive – These are custom classes and can be created by using restrict “C”. These are specified in the attribute “class” in our HTML.
  • Attribute Directive - These attributes are going to add things like behaviors, and we can do so by using restrict "A". You can then provide a linking function, which is where you will put whatever the behavior is.
  • Element Directive – These elements are custom elements, and can be created by using restrict “E”.

We can restrict the directive to both attribute and element by using restrict to “EA”.

In order to register a directive, we will use the module’s directive() function, which receives directive name and a factory function as inputs.

JavaScript
var myApp = angular.module("myApp", [] );

myApp.directive("myDirective", function(){
              return {
              }
});

Factory function returns the implementation of the directive.

Sample Directive – Inline Template Directive

Let us create a sample inline template directive. We are writing our JavaScript code in an external file app.js and importing it to the main HTML file. We are creating an element and attribute directive, so restrict is set to ‘AE’.

App.js

JavaScript
var app = angular.module('custom',[]);
            app.directive("welcome", function(){
                        return {
                                    restrict: "AE",
                                    template: "<div>Hi Everyone! These are custom directives! </div>"
                        }
            });

Main.html

HTML
<body ng-app="custom">
                           <welcome></welcome>
 </body>

Since we are using element directive, we are providing “welcome” as an element in our HTML. If we restrict it to attribute (A), then we can provide “welcome” as an attribute to any element. For example: 

HTML
<div welcome> </div>

 If we restrict it to class (C), then we can provide “welcome” as a class in our HTML. For example:

HTML
<div class="welcome"> </div>

Sample Directive – External Template Directive

Let us create a sample external template directive. We are writing our JavaScript code in an external file app.js and importing it to the main HTML file. We create an external template file name-def.html and specify it in templateUrl of the directive definition. We are creating an element directive, so restrict is set to ‘E’.

Index.html

HTML
<html>
            <head>
                        <title> My FirstApp </title>
                        <script src="Resources\angular.min.js"></script>
                        <script src="app.js" type="text/javascript"></script>
            </head>
            <body>
                        <div ng-app="myApp" ng-controller="MainController">
                                    <name-def> </name-def>
                        </div>
            </body>
</html>

We have given our custom element <name-def> in the index file, so whatever functionality we have given in the directive definition will be implemented inside this tag.

App.js

JavaScript
var app = angular.module('myApp', []);
app.controller('MainController', function($scope){
            $scope.data= [{firstname:"naveen",lastname:"kumar"},
                          {firstname:"Hello",lastname:"world"}
                         ];
});

app.directive('nameDef', function () {
return {
    restrict: 'E',
    templateUrl: 'name-def.html’
   };
});

Instead of template, we are using templateUrl and storing our template in an eternal HTML file.

Name-def.html

HTML
<li ng-repeat="x in data"> {{x.firstname+" "+ x.lastname}} </li>

In the external file, we have used list to display the names list. The output of the above will be:

Image 2

Conclusion

So, we have seen one of the most important features of AngularJS that is custom directives. These are reusable components that can be used whenever needed in our application, just by specifying them as element/attribute/class in our HTML based on the restriction we have provided in the directive definition. Since these are reusable components, we can avoid code duplication in our code using AngularJS, and this feature enables us to code the application efficiently.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)