AngularJs : Custom directives

Directives are markers on a DOM element (such as an attribute, element name, comment or CSS class) that tell AngularJS’s HTML compiler ($compile) to attach a specified behavior to that DOM element (e.g. via event listeners), or even to transform the DOM element and its children. Angular comes with a set of these directives built-in, like ngBind, ngModel, etc. There may be cases where these built in directives does not fit into the requirement, so angular gives you flexibility to create your own custom directives.

Before we start, lets take a look into Normalization. AngularJs follows certain standards when creating reusable components. Angular normalizes an element’s tag and attribute name to determine which elements match which directives. Usually we refer to directives in the DOM by lower-case forms, typically using dash-delimited attributes on DOM elements (eg. my-directive) and in js we refer to directives by their case-sensitive camelCase normalized name (eg. myDirective).

The normalization process is as follows:

  1. Strip x- and data- from the front of the element/attributes.
  2. Convert the :, -, or _-delimited name to camelCase.

Lets built our first directive. index.html:


<!DOCTYPE html>
<html lang="en-us" ng-app="angularApp">
<head>
<title>Html Link Fragments</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
</head>
<body>

<header>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand">AngularJS Demo</a>
</div>
</div>
</nav>
</header>
<div class="container" ng-controller="mainController">
<div class="list-group">
<book-result></book-result>
</div>
</div>
</body>
<script src="https://code.angularjs.org/1.4.8/angular.min.js"></script>
<script src="../js/main.js"></script>
</html>

Notice our custom html tag – <book-result>

main.js:


var myApp = angular.module('angularApp', []);
myApp.controller('mainController', ['$scope', function($scope) {

}]);

myApp.directive("bookResult", function(){

return{
template:'<a href="#" class="list-group-item">BookResult</a>'
}

});

We create a directive using the directive function. Note that the name of directive (bookResult) is the normalize camelCase form of the element in html (book-result). This is very important. When the DOM gets loaded and angular sees the custom element in view it searches for the corresponding directive. As you can see, the directive returns an object. Angular fetches the template property and puts it in the element in html. You can also use angular data binding features in this template and it will be resolved during run time.

customDirective1

Notice the template part is inserted in to the <book-result> element. You can use replace property to replace it all.


myApp.directive("bookResult", function(){

return{
template:'<a href="#" class="list-group-item">BookResult</a>',
replace:true
}

});

Directive types – $compile can match directives based on element names, attributes, class names, as well as comments. By default only elements and attributes are enabled. To enable rest you can use restrict property inside your directive, and it can be A (Attribute), C (Class), E (Element), and M (coMment). index.html

</p>
<!DOCTYPE html>
<html lang="en-us" ng-app="angularApp">
<head>
<title>Html Link Fragments</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" />
</head>
<body>

<header>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand">AngularJS Demo</a>
</div>
</div>
</nav>
</header>
<div class="container" ng-controller="mainController">
<div class="list-group">
<book-result></book-result>
<div book-result></div>
<div class="book-result"></div>
<!-- directive: book-result -->
</div>
</div>
</body>
<script src="https://code.angularjs.org/1.4.8/angular.min.js"></script>
<script src="../js/main.js"></script>
</html>
<p class="ng-scope">

main.js


var myApp = angular.module('angularApp', []);
myApp.controller('mainController', ['$scope', function($scope) {

}]);

myApp.directive("bookResult", function(){

return{
restrict:'EACM',
template:'<a href="#" class="list-group-item">BookResult</a>',
replace:true
}

});

customDirective2

Placing your html in the template property may not be easy all the time if your html becomes big. You can use the templateUrl property to keep your html in a different file. changing main.js:


var myApp = angular.module('angularApp', []);
myApp.controller('mainController', ['$scope', function($scope) {

}]);

myApp.directive("bookResult", function(){

return{
templateUrl:'directives/bookResultDirective.html',
replace:true
}

});

bookResultDirective.html


<a href="#" class="list-group-item">BookResult</a>

customDirective3

Also notice that we have only 2 rows now since by default angular enables only element and atribute directives.

By default, directives have access to its parent scope. So we have some property in $scope that can be accessed inside the directive. main.js


var myApp = angular.module('angularApp', []);
myApp.controller('mainController', ['$scope', function($scope) {

$scope.book={
title:'Book1',
description:'Book1 description'
}

}]);

myApp.directive("bookResult", function(){

return{
templateUrl:'directives/bookResultDirective.html',
replace:true
}

});

So we have a book property in our $scope object. Lets use it in our bookResultDirective.html


<a href="#" class="list-group-item">
<h4>{{book.title}}</h4>
<p>{{book.description}}</p>
</a>

customDirective4

 

Advertisements
%d bloggers like this: