0

Consider we have some directive with templateUrl and controller.

angular.module('someApp').directive('myDirective', [function() {
    return {
        templateUrl:'someTemplate.html',
        controller: ['$scope', function($scope) {
            this.someFunction = function() {}
        }]        
    }
}])

If we try to get controller now

var directive = angular.element('<my-directive />');
$compile(directive)( scope );
var controller = directive.controller('myDirective');

the controller is undefined.

andrfas
  • 1,320
  • 2
  • 10
  • 16
  • What are you actually trying to accomplish? In other words, why do you have the need to get the controller? Perhaps there is a better approach – New Dev Jul 26 '15 at 06:59
  • I need to manage (create, set data) my directive from a service. For that purpose i have functions in controller of directive (i read in documentation that directive can use its controller to expose an API). So i need to get a controller of directive to use those functions. To be honest, i'm strongly doubt in that approach, but can't find any other solution. – andrfas Jul 27 '15 at 14:01
  • 1
    "...controller to expose an API" is correct, but it is meant for other directives that `require` your directive. This is not meant as an API to a Service or a Controller that should not even be dealing with DOM. So, I'm not clear what you mean by "manage my directive from a service". Services should manage data - not directives – New Dev Jul 27 '15 at 14:37
  • Thank you for your answers - you describes for me really important things. So i understood the mistake with service. But consider i need to create a directive - where should i do it? And after that, how can i set some data to the directive's scope? – andrfas Jul 27 '15 at 20:20
  • It's quite rare that one needs to `$compile(template)`. In a typical usage, directives are declared in the HTML - they are distinct pieces of DOM functionality. Controllers and Services deal with Models and View Models - not directives. Data can be passed via attributes (with one- and two-way bindings) or via scope inheritance, although this is reduces the directives' reusability. I suggest to [read this](http://stackoverflow.com/a/15012542/968155) to understand better. – New Dev Jul 29 '15 at 21:39

1 Answers1

0

The answer is to set a template instead of templateUrl in the directive.

 angular.module('someApp').directive('myDirective', [function() {
        return {
            template:'<span>Solution!</span>',
            controller: ['$scope', function($scope) {
                this.someFunction = function() {}
            }]        
        }
    }])

I can't find anything about it in documentation. I think it's a bug.

andrfas
  • 1,320
  • 2
  • 10
  • 16
  • It's not a bug - with `templateUrl`, since the template is being fetched asynchronously, Angular doesn't hold off on compilation process until it arrives. The `$compile` call become asynchronous. With `template`, the call is synchronous and the directive is compiled/linked synchronously as well – New Dev Jul 26 '15 at 06:58
  • To clarify the above... the `$compile` function will still return a link function synchronously, but this would be a delayed link function. The asynchronous part comes from the fact that the actual compilation of `myDirective` is suspended until the template is fetched, and so - no controller yet attached to the element – New Dev Jul 26 '15 at 07:27