AngularJS

Decorators




What are Behaviors ?


A behavior is an object that defines event handlers.

A behavior is an object that injects runtime changes 
into target instances


  • Add Features
  • Modify Features
  • Remove Features
  • Substitute entire instances

Consider AngularJS Startup

define([
    'auth/Session',
    'auth/Authenticator',
    'auth/SessionController'
],
function ( Session, Authenticator, SessionController )
{
    var moduleName = "quizzer.Authenticate";
    angular
        .module(     moduleName,    [ ]                     )
        .service(    "session",           Session           )
        .service(    "authenticator",     Authenticator     )
        .controller( "SessionController", SessionController );

    return moduleName;
});        

Angular uses the above to perform:
  • Registration of constructor functions
  • Instantiation with Dependency Injection

Before Injection occurs,

How do I do the following ?


Change instance behaviors BEFORE injection...
(change, add, or remove functionality)

Substitute our own instance BEFORE injection...
(if I cannot change the registration)

Decorators Visualized



Decorators Visualized



How to configure Decorators?


Use $provide.decorator( )


angular
    .service( "session", Session )
    .config(function( $provide )
    {
        $provide.decorator( "$q",       function( $delegate ){ /* ... */ });
        $provide.decorator( "$log",     function( $delegate ){ /* ... */ });
        $provide.decorator( "session",  function( $delegate ){ /* ... */ });

    });        
    

  • Specify name of instance to decorate
  • Specify function( $delegate )   

Decorate $q Service

angular
    .service( "session", Session )
    .config(function( $provide )
    {
        $provide.decorator( "$q", function( $delegate )
        { 
            // Let's add a `spread()`; useful with $q.all()
            $delegate.spread = function( targetFn,scope )
            {
                return function()
                {
                    var params = [].concat(arguments[0]);
                    targetFn.apply(scope, params);
                };
            };
            return $delegate;
        });
    });
@see Flattening Promise Chains blog
http://bit.ly/1eFNviC

Decorate $log Service


require(['utils/logger/LogEnhancer'], function (enhanceLoggerFn)
{
     angular.module( 'MyApp', [ ])
            .config(function( $provide )
            {
                $provide.decorator( "$log", function( $delegate )
                { 
                    enhanceLoggerFn($delegate);
                    return $delegate;
                });
            });
}
Head-hook all $log methods to enhance functionality with timestamps & more...
@see
 angularjs-Quizzler on GitHub
Enhance AngularJS $log blog
Don't   use  Decorators  if:

  • You own the library and want changes for all uses;
    across in multiple apps.
  • Registration & substitution changes are possible


Do  use  Decorators  if:

  • Cannot intercept registration 
  • Extending NG-specific instances
  • Extending library features for single use

about ME


Thomas Burleson


Need a senior, front-end architect ?
I am looking for the next great project...