Building Custom Angular.js Directives

Kirjoitettu - Viimeisin muokkaus

I've written about some basic parts of the Angular.js UI Web framework in another article, so I will not cover those basics again. In this article, I will cover how to create custom directives with Angular and how can you use those in your Web applications.

What are directives?

If you are coming from desktop application development, an Angular.js directive can be considered as a custom control created for a specific purpose, with its own code and UI code. If you have a Web developer background, you can think of directives as a collection of HTML elements that help you to group these and implement functions. By using them, you can benefit from all the goodness that Angular.js provides, like two-way data binding and filters.

How do directives work?

When the Angular application starts (bootstraps) it's inner “HTML compiler” parses the HTML code and matches directives to the defined tags/attributes in the markup. When this matching happens, events are created and hooked between markup and the directives.

There is a naming convention used for directives, in the markup the data prefix should be used in front of custom directives:

<div data-employee-time-sheet id=”employee_time_sheet” />

When Angular parses the HTML markup, it omits the data prefix and removes the “-” from the attribute. It converts the name to camelCase and looks for a directive within the JavaScript that has the same name; in this case, Angular will look for a directive named employeeTimeSheet.

I defined a new directive called contactCardInformation. It displays the information about contacts stored in the database and the default image:

                        

The angular code for the directive:

varcontactCardsApp = angular.module('contactCardsApp', []);
contactCardsApp.controller('ContactListCtrl', ['$scope', '$http', function ($scope, $http) {
    $scope.contacts = [];        
    $http.get('/contact/John')
        .success(function (response) {
            $scope.contacts = response;            
        })
        .error(function (error) {
             console.log(error);
             alert(error);
        });
}])
.directive('contactCardInformation', function(){
return {
      templateUrl: '/contact/template/contactCard'
    };
});

I declared a module called contactCardsAppandadded a controller, called ContactListCtrl, to the module. The controller has the $scope and $http services injected. Inside the controller I created the contacts array, then I sent an HTTP GET request to the server to load the data (the URL /contact/John loaded all the users that have John set as their first_name). When the response from the servers arrived, I stored the response in the $scope.contacts array. If there was an error, I logged it to the console and also alerted the user. The data in $scope.contacts was used by the directive.

After I had defined the controller, I created my new directive. Directives are defined on the module level; the same way controllers are. All the directive did was return a template that had angular-specific code:

Contacts loaded from database: {{ contacts.length }}
<div ng-repeat="contact in contacts">
	<div class="contact">
		<div class="contact_data">
		<p><strong>Name:</strong>{{contact.first_name}} {{contact.last_name}} </p>
<p><strong>Website:</strong> {{contact.website}}</p>
<p><strong>Age:</strong> {{contact.age}}</p>
<p><strong>Mobile:</strong> {{contact.mobile_phone }}</p>
<p><strong>ID:</strong> {{contact._id}}</p>
		</div>	
		<div class="contact_image">
			img(src="/images/custom_user.jpg")
		</div>
	</div>
</div>

In the first line I displayed how many contacts were loaded from the database. Then I used the ng-repeat directive to create a new div element for each contact loaded from the database.

Inside the div element, I created two separate divs: one for contact_data and one for contact_image.

When I wanted to use my new directive all I needed to do was to add the attribute data-contact-card-information to a new div and Angular resolved everything else for me.

I was using Jade as a template engine in my project, which explains why the code is not HTML:

extends layout
block content
        h1= title
p Welcome to #{welcom_message}

div(ng-app='contactCardsApp')
div(ng-controller='ContactListCtrl')
div(data-contact-card-information)
script(src='https://ajax.googleapis..../angular.min.js')
script(src='/javascripts/contactCardsApp.js')

Using directives can be convenient when you want to reuse parts of a website or SPA. You can separate the application logic of a directive to a separate controller to seal it from the other parts of the application and make it easier to manage and integrate with other parts of the application.

The code is available at GitHub, in the node_projects repository under the express_contacts project.

Ilmoitettu 6 maaliskuuta, 2015

Greg Bogdan

Software Engineer, Blogger, Tech Enthusiast

I am a Software Engineer with over 7 years of experience in different domains(ERP, Financial Products and Alerting Systems). My main expertise is .NET, Java, Python and JavaScript. I like technical writing and have good experience in creating tutorials and how to technical articles. I am passionate about technology and I love what I do and I always intend to 100% fulfill the project which I am ...

Seuraava artikkeli

An Introduction to Internet Marketing