a.k.a. “Modifying the behavior of AngularJS’ core services”
After using Batarang, I wondered how they are able to collect performance metrics at this level of detail. Thoughts full of horrible code rushed to my mind. I opened the source code in fear, always ready to close it as fast as possible. After some reading, I discovered these lines:
Where once was fear there is now only awesome! I just discovered another well-architected feature of AngularJS, which – unfortunately – isn’t well documented.
Meet the decorator pattern
In software design, a decorator is an object that modifies the behaviour of another, already existing object without touching its code. This is achieved by wrapping either the whole object or just parts of it and then using the wrapped object instead of the original one.
Decorators in Angular
Let’s create a basic AngularJS decorator to modify the behavior of the popular ngResource service:
This code will prepend
'/api/v1' to all your
$resource REST urls. Therefore, when you define new models with
$resource('/model'), they will use
To accomplish that, we create a new module named
ngResource+apiPrefix that depends on
ngResource. We call
$provide.decorate() and pass in the name of the service we want to decorate, along with a function whose parameters are going to be injected.
$delegate argument is resolved with an instance of the specified service. We now replace the original
$resource function with a new one that does three things:
- Prepend a common
API_PREFIXto the resource url.
- Invoke the original
$resourcefunction with the modified arguments
- Return the original object
In order to load this decorator, we would have to load the module:
From now on, all instances of
$resource are decorated. There’s no way to access the original
$resource service again.
The snippet above is a little verbose, because it has some boilerplate code in it. We can get rid of that by using the angular-decorate plugin.
Simple, isn’t it?
By the way, the plus sign in the module name is a convention that orginates in ObjectiveC and helps to identify the intention of a decorator.