Tomer Tomer - 21 days ago 10
AngularJS Question

Angular $compile with required controller

I have a composite list directive - that is - a list item that can be a list himself.

The parent directive defines the controller:

.directive('parent', function() {
controller: function($scope) {
},
link: function (scope, element, attrs) {
}
})


The list (of items) requires the parent controller which by itself works fine (why shouldn't it..):

.directive('list', function() {
require: '^parent',
link: function (scope, element, attrs, parentCtrl) {
}
})


The same goes as well for the concrete item, which is also fine:

.directive('item', function() {
require: '^parent',
link: function (scope, element, attrs, parentCtrl) {
}
})


An item may be a composite in which case it creates a "list" himself. This composition is done by $compile (ing) a list item inside the link function:

link: function (scope, element, attrs, parentCtrl) {
...
$compile("<list></list>")(scope)
...
}


Which throws an exception:

Controller 'parent', required by directive 'list', can't be found!


The reason for this is obvious - the $compile function didn't provide the controller and therefore the requirement of 'parent' cannot be resolved.

And so I've tried providing the controller manually:

$compile("<list></list>")(scope, null, {'parent': parentCtrl});


Which doesn't throws an exception but still doesn't provide this controller when needed.



Any idea how to make the $compile function accept an external controllers which should be evaluated as well?

Answer

For future reference, here is the solution:

On the $compile function the required controller can be passed as the transcluded controller:

$compile(template)(scope, undefined, {transcludeControllers: injectedCtrl})

Where the "injectedCtrl" is the object which lists controllers the directive expects, for example if you require: '^dad', then transcludeControllers look like this:

 transcludeControllers: {
        dad: { //name of controller in 'require' statement
          instance: vm //instance of controller
        }
      }

See this example: https://jsfiddle.net/qq4gqn6t/11/


Thats it!

Comments