Monday, May 5, 2014

AngularJS Directives

Directive Properties
In the previous mySharedScope directive a single property named template was defined in the object literal returned from the function. This property is responsible for defining the template code (a data binding expression in this case) that should be used to generate HTML. What other properties are available to use?
Custom directives will typically return an object literal that is responsible for defining properties needed by the directive such as templates, a controller (if one is used), DOM manipulation code, and more. Several different properties can be used (you’ll find a complete list of them here). Here’s a look at a few of the key properties that you may come across and an example of using them:

angular.module('moduleName')
    .directive('myDirective', function () {
    return {
        restrict: 'EA', //E = element, A = attribute, C = class, M = comment         
        scope: {
            //@ reads the attribute value, = provides two-way binding, & works with functions
            title: '@'         },
        template: '<div>{{ myVal }}</div>',
        templateUrl: 'mytemplate.html',
        controller: controllerFunction, //Embed a custom controller in the directive
        link: function ($scope, element, attrs) { } //DOM manipulation
    }
});

A short explanation of each of the properties is shown next:

PropertyDescription
restrictDetermines where a directive can be used (as an element, attribute, CSS class, or comment).
scopeUsed to create a new child scope or an isolate scope.
templateDefines the content that should be output from the directive. Can include HTML, data binding expressions, and even other directives.
templateUrlProvides the path to the template that should be used by the directive. It can optionally contain a DOM element id when templates are defined in <script> tags.
controllerUsed to define the controller that will be associated with the directive template.
linkFunction used for DOM manipulation tasks.

Manipulating the DOM

In addition to performing data binding operations with templates (and there’s much more to that story that I’ll cover in future posts!), directives can also be used to manipulate the DOM. This is done using the link function shown earlier.
The link function normally accepts 3 parameters (although others can be passed in some situations) including the scope, the element that the directive is associated with, and the attributes of the target element. An example of a directive that handles click, mouseenter, and mouseleave events on an element is shown next:

app.directive('myDomDirective', function () {
    return {
        link: function ($scope, element, attrs) {
            element.bind('click', function () {
                element.html('You clicked me!');
            });
            element.bind('mouseenter', function () {
                element.css('background-color', 'yellow');
            });
            element.bind('mouseleave', function () {
                element.css('background-color', 'white');
            });
        }
    };
});

To use the directive you can add the following code into the view:

<div my-dom-directive>Click Me!</div>

As the mouse enters or leaves the <div> the background color will change between yellow and white (yes, embedded styles are used in this simple example but CSS classes can certainly be used as well). When the target element is clicked the inner HTML is changed to “You clicked me!”. There’s of course much, much more you can do when it comes to DOM manipulating but this should help get you started.

Structuring AngularJS Directive Code

Although the mySharedScope and myDomDirective directives work fine, I like to follow a specific pattern when defining directives and other AngularJS components. Here’s an example:

(function () {

    var directive = function () {
        return {

        };
    };

    angular.module('moduleName')
        .directive('directiveName', directive);

}());

This code wraps everything with an immediately invoked function to pull everything out of the global scope. It then defines the directive functionality in a function assigned to the directivevariable. Finally, a call is made to the module’s directive() function and the directive variable is passed in. There are several other techniques that can be used to structure code (see my previous post on the subject) but this is the general pattern I like to follow.

Summary

In this first post on AngularJS directives you’ve seen some of the fundamentals and learned how to create two basic directives. We’ve barely scratched the surface though! In the next post I’ll discuss isolate scope and different properties referred to as local scope properties that can be used for data binding and much more.

No comments:

Post a Comment