Reputation: 3857
I have some items stored in a database. Each item has a 'type'. I want to use this type to dynamically insert a directive based on the type. My html would look like:
<ul>
<li my-item ng-repeat="item in items"></li>
</ul
In the my-item
directive I dynamically generate a directive as follows:
app.directive('myItem', function($compile){
return {
link: function(scope, el, attrs) {
var concreteTypeEl = $compile('<div my-item-' + scope.item.type + ' item="item"></div>')(scope);
el.append(concreteTypeEl);
}
};
});
And then I have further directives defining the 'concrete' item type. For example an item with type 'Type1' would use the 'myItemType1' directive (shown below)
So that's all fine. Now, I also want a parent directive to wrap all instances of these directives and provide a controller to allow coordination between them.
I use the require ^parentCtrl
syntax on the myItem
directive to access the parent controller.
My problem is that this doesn't work for any of the 'dynamically' inserted directives such as 'myItemType1'
Full example below and in this plunkr. The markup:
<body ng-controller="MainCtrl">
<div my-container>
<ul>
<li my-item ng-repeat="item in items"></li>
</ul>
</div>
</body>
The code:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.items = [{
type: 'type1',
content: 'Type 1 item'
}, {
type: 'type1',
content: 'Another Type 1 item'
}];
});
app.directive('myContainer', function(){
return {
controller: function() {
this.doSomething = function() {
return 'foo';
}
}
};
});
app.directive('myItem', function($compile){
return {
require: '^myContainer',
link: function(scope, el, attrs, myContainer) {
// 'myContainer' is a reference to parent controller
console.log('Ctrl in myItem:', myContainer);
var concreteTypeEl = $compile('<div my-item-' + scope.item.type + ' item="item"></div>')(scope);
el.append(concreteTypeEl);
}
};
});
app.directive('myItemType1', function($compile){
return {
require: '?^myContainer',
link: function(scope, el, attrs, myContainer) {
// PROBLEM: 'myContainer' is undefined here
console.log('Ctrl in myItemType1:', myContainer);
el.append(scope.item.content);
}
};
});
Am I approaching this all wrong?
Upvotes: 2
Views: 655
Reputation: 52867
You should append the element to the DOM tree before you manually compile and link it:
link:function(scope,element,attr) {
// create the element
var e = angular.element('<my-child></my-child>');
//append it to the DOM
element.append(e);
// compile and link
$compile(e)(scope);
}
Upvotes: 3