TL;DR: Is there a way to dynamically set a directive based on a parameter value? Something similar to ng-class
for setting css elements, but a way to set the directive based on the value in the scope. I would have the value in the scope so I could call:
<div class="data.directiveType"></div>
When
data.directiveType = "my-directive"
the div would become
<div class="my-directive"></div>
and myDirective would be invoked?
Detailed Question:
What I am trying to do is allow the user to add elements to the web application and I wanted the directive for each element to be added based on what the user clicks.
I have the following Directives:
app.directive("mySuperman", function(){
//directive logic
});
app.directive("myBatman", function(){
//directive logic
});
app.directive("myWonderWoman", function(){
//directive logic
});
I have the following controller
app.controller("ParentCtrl", function($scope){
$scope.superHeros = [];
var superman = {directiveType: "my-superman"};
var batman = {directiveType: "my-batman"};
var wonderWoman = {directiveType: "my-wonder-woman"}
$scope.addBatman = function()
{
var batmanInstance = {}
angular.copy(batman, batmanInstance);
$scope.superHeros.push(batmanInstance);
}
$scope.addSuperman = function()
{
var supermanInstance = {}
angular.copy(superman, supermanInstance);
$scope.superHeros.push(supermanInstance);
}
$scope.addWonderWoman = function()
{
var wonderwomanInstance = {}
angular.copy(wonderWoman, wonderwomanInstance);
$scope.superHeros.push(wonderwomanInstance);
}
});
In the index.html I have
<body ng-controller="ParentCtrl>
<a ng-click="addBatman()">Add Batman</a>
<a ng-click="addSuperman()">Add Superman</a>
<a ng-click="addWonderWoman()">Add WonderWoman</a>
<div ng-repeat="hero in superHeros">
<!-- The following doesn't work, but it is the functionality I am trying to achieve -->
<div class={{hero.directiveType}}></div>
<div>
</body>
The other way I thought of doing this was just using ng-include
in the ng-repeat
and adding the template url to the hero
object instead of the directive type, but I was hoping there was a cleaner way that I could make better use of the data binding and not have to call ng-include
just to call another directive.
You can create a directive that takes the directive to add as a parameter, adds it to the element and compiles it. Then use it like this:
<div ng-repeat="hero in superHeros">
<div add-directive="hero.directiveType"></div>
</div>
Here is a basic example:
app.directive('addDirective', function($parse, $compile) {
return {
compile: function compile(tElement, tAttrs) {
var directiveGetter = $parse(tAttrs.addDirective);
return function postLink(scope, element) {
element.removeAttr('add-directive');
var directive = directiveGetter(scope);
element.attr(directive, '');
$compile(element)(scope);
};
}
};
});