NG Directives



Why Directives?


  1. "Web components" (upcoming implementation of w3 spec)
  2. Think "reusable" and "encapsulated"
  3. Angular being awesome

Example



Imagine a loading indicator:




  1. Used in many places
  2. Needs to be shown/hidden based on pending API call
  3. Might have custom code

<img src="/my/asset/loader.gif" id="loader" />
<script>
  // ... awesome script to hide/show loader based on promises...
</script>

This would have to be duplicated in every page.

Or in Angular, every controller + view.

Solution: directives


Directives are  custom "widgets" of view/logic that are
  • Reusable
  • Encapsulated

Basic Structure of a Directive


 myApp.directive('myLoader', function($compile) {
    return {
        restrict: 'A',
        template: '<img src="http://i.stack.imgur.com/MnyxU.gif" />'    }
}

  • return an object with certain directive-specific keys
  • name "myLoader" will be interpreted in NG as "my-loader"

When to write a directive


DRY
Reuse, ease of use
When it makes your code simpler, not more complex

When not to write a directive


For directives that already exist!
For something that will only be done once
For something trivial

Directives should be the most reduce-able piece of functionality/presentation that you can manage.

If it can easily be done using standard views/controllers and isn't re-used, probably not a good time to write a directive.

"Restrict"


Element

Attribute

Class

Comment

'Template'


Can use markup or templateUrl to point to remote HTML file

Controller


Create a custom controller with logic, dependency injection, etc. all encapsulated inside the directive itself.

Require


You can "require" the presence of attrs (controllers or directives)

angular.module('docsTabsExample', []).directive('myPane', function() {
  return {
    require: ['^myTabs', '^ngModel'],
    restrict: 'E',
    transclude: true,
    scope: {
      title: '@'
    },
    link: function(scope, element, attrs, controllers) {
      var tabsCtrl = controllers[0],
          modelCtrl = controllers[1];
      tabsCtrl.addPane(scope);
    },
    templateUrl: 'my-pane.html'
  };
}); 

"Link" function


Bind to events, observe variable changes

link: function(scope, element, attrs, controller) {
    element.on('keydown', function(event) {        alert('key');    })
    element.$observe('email', function(old, new) {

    })
} 
scope is own scope (if isolated) or parent
element is jQuery lite wrapped element
attrs is object map of all element attributes

[BREAK]

Isolating scope

creating a scope for your directive

"@"
string will be evaluated before passing

"="
value/object

"&"
method that executes in parent scope

"Transclusion"


Wrapping content with a directive

<my-custom-directive>
     <span>Some Awesome text</span>
     <div>Some other stuff</div>
</my-custom-directive>

transclude: true 
will include child elements in the scope of the directive

transclude: element 
will include the entire element and its children

NG Directives

By Cahlan Sharp

NG Directives

  • 1,065