Writing Custom Directives is Easy Right?

AngularJS directives can be a bit intimidating the first time you see them. They offer many different options, have a few cryptic features (and cryptic is my politically correct term for “what were they thinking here?”), and are generally challenging at first. However, once you understand the pieces and how they fit together you’ll find that they’re not that bad. I compare it to learning to play an instrument. The first time you play a piano or guitar you aren’t very good and feel completely incompetent. However, after putting in the necessary practice time you end up getting pretty good and capable of handling more advanced music. It’s the same with directives – they take a little practice but you can do powerful things with them once you get the hang of it. I do look forward to the day where features found in the Polymer project and Web Components spec replace the directives that we write today. Check out those links if you want a glimpse into the future direction of directives.

 

Getting Started with Custom Directives

Why would you want to write a custom directive? Let’s say that you’ve been tasked with converting a collection of customers into some type of grid that’s displayed in a view. Although you can certainly add DOM functionality into a controller to handle this, doing that would make it hard to test the controller and breaks the separation of concerns – you just don’t want to do that in an AngularJS application. Instead, that type of functionality should go into a custom directive. In another case you may have some data binding that occurs across many views and you want to re-use the data binding expressions. While a child view loaded with ng-include (more on this in a moment) could be used, directives also work well in this scenario. There are numerous other ways that custom directives can be used, these examples are only scratching the surface.

Let’s start by looking an a very basic example of an AngularJS directive. Assume that we have the following module and controller defined in the application (I’ll refer to this module and controller in future posts as well):

var app = angular.module('directivesModule', []);

app.controller('CustomersController', ['$scope', function ($scope) {
    var counter = 0;
    $scope.customer = {
        name: 'David',
        street: '1234 Anywhere St.'
    };
    
    $scope.customers = [
        {
            name: 'David',
            street: '1234 Anywhere St.'
        },
        {
            name: 'Tina',
            street: '1800 Crest St.'
        },
        {
            name: 'Michelle',
            street: '890 Main St.'
        }
    ];

    $scope.addCustomer = function () {
        counter++;
        $scope.customers.push({
            name: 'New Customer' + counter,
            street: counter + ' Cedar Point St.'
        });
    };

    $scope.changeData = function () {
        counter++;
        $scope.customer = {
            name: 'James',
            street: counter + ' Cedar Point St.'
        };
    };
}]);

Let’s say that we find ourselves writing out a data binding expression similar to the following over and over in views throughout the app:

 

Name: {{customer.name}} 
<br />
Street: {{customer.street}}

 

One technique that can be used to promote re-use is to place the data binding template into a child view (I’ll call it myChildView.html) and reference it from within a parent view using the ng-include directive. This allowsmyChildView.html to be re-used throughout the application wherever it’s needed.

 

<div ng-include="'myChildView.html'"></div>

 

Leave a Reply

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