13

I'm trying to use Angular's "decorator" capability to add functionality to some directives. Assume that my directive's name is myDirective. My code looks like this:

angular.module('app').config([
  '$provide', function($provide) {
    return $provide.decorator('myDirective', [
      '$delegate', '$log', function($delegate, $log) {
        // TODO - It worked!  Do something to modify the behavior

        $log.info("In decorator");
      }
    ]);
  }

]);

I keep getting this message:

Uncaught Error: [$injector:unpr] Unknown provider: myDirectiveProvider from app 

To the best of my ability, the directives are already registered by the time the decorator function runs. Any insight would be appreciated!

blaster
  • 8,876
  • 11
  • 48
  • 77
  • See: http://stackoverflow.com/questions/18335574/decorating-the-ng-click-directive-in-angularjs – XML Mar 21 '14 at 20:01

2 Answers2

22

This article shows how you can, in fact, use decorator() with directives.

You just have to include "Directive" as the suffix for the name. Hence, in my example I should have been doing

return $provide.decorator('myDirectiveDirective', ['$delegate', '$log', function($delegate, $log) {
    // TODO - It worked!  Do something to modify the behavior
    $log.info("In decorator");

    // Article uses index 0 but I found that index 0 was "window" and index 1 was the directive
    var directive = $delegate[1];
}

http://angular-tips.com/blog/2013/09/experiment-decorating-directives/

blaster
  • 8,876
  • 11
  • 48
  • 77
  • 1
    Fantastic, you learn something every day. Looking at the code, it seems `$delegate` should be a list of all of the directives in all loaded modules with the name `myDirective`. Seems potentially worrying that index 0 would be window, unless I'm missing something. You would have to watch out as the order in `$delegate` will depend on what order modules and directives are defined, so you'd need to keep this consistent. You may also want to remove unwanted directives from the list (`window`) - I'd still lean to sticking to documented ways unless you have to, but if you must this is very useful! – Andyrooger Oct 16 '13 at 21:10
  • Adding the 'Directive' suffix is crucial! – Leon Aug 10 '15 at 02:39
  • This move doesn't work anymore, angular 1.4.x only allows the use of decorators in providers and services. – Juan Biscaia Aug 25 '15 at 18:52
  • 3
    Juan, do u have a URL for this? – Nick Nov 04 '15 at 21:47
  • Maybe I am tired but I put Decorator instead of Directive! Thanks – jemiloii Nov 09 '16 at 22:01
1

Decorators as created with the decorator method are for services only. They have to be created with service, factory, provider or value. See the docs here.

If you want to decorate a directive, you can make another directive with the same name. Both directives will be used when the DOM is compiled, and you can define the compilation order using priority.

Alternatively, if you are able to modify the code that uses the directive you are trying to decorate, then you can just make a new directive that uses the original in its template.

Andyrooger
  • 6,748
  • 1
  • 43
  • 44
  • 2
    I found that you can use decorator for directives if you include "Directive" as the suffix for the name. Hence, in my example I should have been doing $provide.decorator('myDirectiveDirective' ... – blaster Oct 16 '13 at 18:57
  • 3
    This is incorrect. See @blaster's self-answer, which shows how to decorate directives. – XML Mar 21 '14 at 20:00