Creating an #AngularJS Directive

Index:

  1. Getting started with AngularJS
  2. Creating an AngularJS Controller
  3. The AngularJS $scope is not the MVC Model
  4. Using repeating elements in AngularJS
  5. Filtering the data in an AngularJS ngRepeat element
  6. Using the AngularJS FormController to control form submission
  7. Creating an AngularJS Directive
  8. Using the DOM in an AngularJS application
  9. To SPA or not to SPA

 

One of the more powerful aspects of AngularJS are directives. So far we have used a few build in directives but we are by no means limited to the build in ones. In fact creating your own directives is highly recommended as that can turn HTML into a domain specific language if you want that. Now starting with directives has a bit of a learning curve but that is certainly worth the effort!

 

What is an AngularJS directive?

The easies way to think about a directive is as a reusable piece of markup. Just as we create functions when programming to create reusable pieces of code and we create reusable CSS styles we would like to create reusable HTML parts. Unfortunately HTML itself doesn’t allow us to do that so we normally end up with copying a lot of markup with no reuse making the whole thing a lot less maintainable.

With AngularJS we can use directives to create these reusable pieces of HTML and make our application markup just as maintainable as our code and style sheets.

 

An example using Bootstrap 3

These days Bootstrap is pretty much the standard CSS framework so lets create a simple input form using this. Creating a simple input form with a horizontal layout is easy enough with just the basic Bootstrap included.

image

However the markup required for each element is quite verbose resulting in quite a long bit of markup for this simple form. This is because each input element/label combination takes up 6 lines of markup. And worse of all is that they are mostly identical.

   1: <body ng-app="contactsApp" ng-controller="ContactsEditorCtrl">

   2:     <form class="form-horizontal" role="form">

   3:         <div class="form-group">

   4:             <label class="col-lg-2 control-label">Firstname</label>

   5:             <div class="col-lg-8">

   6:                 <input type="text" class="form-control" ng-model="person.firstName">

   7:             </div>

   8:         </div>

   9:  

  10:         <div class="form-group">

  11:             <label class="col-lg-2 control-label">Lastname</label>

  12:             <div class="col-lg-8">

  13:                 <input type="text" class="form-control" ng-model="person.lastName">

  14:             </div>

  15:         </div>

  16:  

  17:         <div class="form-group">

  18:             <label class="col-lg-2 control-label">Gender</label>

  19:             <div class="col-lg-8">

  20:                 <input type="text" class="form-control" ng-model="person.gender">

  21:             </div>

  22:         </div>

  23:  

  24:         <div class="form-group">

  25:             <label class="col-lg-2 control-label">Company</label>

  26:             <div class="col-lg-8">

  27:                 <input type="text" class="form-control" ng-model="person.company">

  28:             </div>

  29:         </div>

  30:  

  31:         <div class="form-group">

  32:             <label class="col-lg-2 control-label">Email</label>

  33:             <div class="col-lg-8">

  34:                 <input type="text" class="form-control" ng-model="person.email">

  35:             </div>

  36:         </div>

  37:  

  38:         <div class="form-group">

  39:             <label class="col-lg-2 control-label">Address</label>

  40:             <div class="col-lg-8">

  41:                 <input type="text" class="form-control" ng-model="person.address">

  42:             </div>

  43:         </div>

  44:  

  45:         <div class="form-group">

  46:             <label class="col-lg-2 control-label">City</label>

  47:             <div class="col-lg-8">

  48:                 <input type="text" class="form-control" ng-model="person.city">

  49:             </div>

  50:         </div>

  51:  

  52:         <div class="form-group">

  53:             <label class="col-lg-2 control-label">Country</label>

  54:             <div class="col-lg-8">

  55:                 <input type="text" class="form-control" ng-model="person.country">

  56:             </div>

  57:         </div>

  58:  

  59:  

  60:         <div class="form-group">

  61:             <div class="col-lg-offset-2 col-lg-8">

  62:                 <button type="submit" class="btn btn-default">Save</button>

  63:             </div>

  64:         </div>

  65:     </form>

  66:  

  67:     <script src="Scripts/angular.js"></script>
   1:  

   2:     <script src="App/Contacts/App.js">
</script>

  68: </body>

 

Creating the same input form using an AngularJS directive

Once we have created the appropriate AngularJS directive we can shrink the HTML markup to just the code below. I don’t know about you but I most certainly prefer to maintain the markup below :-)

 

   1: <body ng-app="contactsApp" ng-controller="ContactsEditorCtrl">

   2:     <form class="form-horizontal" role="form">

   3:         <my-input ng-model="person.firstName" my-label="Firstname"></my-input>

   4:         <my-input ng-model="person.lastName" my-label="Lastname"></my-input>

   5:         <my-input ng-model="person.gender" my-label="Gender"></my-input>

   6:         <my-input ng-model="person.company" my-label="Company"></my-input>

   7:         <my-input ng-model="person.email" my-label="Email"></my-input>

   8:         <my-input ng-model="person.address" my-label="Address"></my-input>

   9:         <my-input ng-model="person.city" my-label="City"></my-input>

  10:         <my-input ng-model="person.country" my-label="Country"></my-input>

  11:     </form>

  12:  

  13:     <script src="Scripts/angular.js"></script>
   1:  

   2:     <script src="App/Contacts/App.js">
</script>

  14: </body>

 

Writing the directive

Writing a basic AngularJS Directive is quite easy. There are lots of options but in this case we only need a few basic ones. Once we have defined an AngularJS module we can create a directive by calling the directive function. Because we are not doing anything special all we need to do is provide a function that returns an object that defines the directive.

   1: var app = angular.module("contactsApp", []);

   2:  

   3: app.directive("myInput", function () {

   4:     return {

   5:         scope: {

   6:             ngModel: '=',

   7:             myLabel: '@'

   8:         },

   9:         restrict: 'E',

  10:         template: '<div class="form-group"><label class="col-lg-2 control-label" ng-bind="myLabel"></label><div class="col-lg-8"><input type="text" class="form-control" ng-model="ngModel"></div></div>'

  11:     };

  12: });


 


 


 


Directives can be used in a number of ways but this one is used as an HTML element so we need to specify that using the ‘restrict’ property. Additionally we want to provide some variables per instance, in this case the model property to bind to and the label to display in before the textbox. Additionally we display the template which is basically the HTML template we want to insert in place of the directive itself.


 


This is just a very basic directive, there is a lot more possible. For more info check the documentation.


 


Enjoy!

Leave a Reply

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


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>