0

I have a generic directive

  • genericDirective

that is supposed to choose another specific directive

  • type1 directive if obj.type == "type1"
  • type2 directive if obj.type == "type2"

HTML

<div ng-controller="MainCtrl">
    <div class="genericdirective" ng-repeat="obj in someArray"></div>
</div>

Javascript

var app = angular.module("myApp", []);

app.controller("MainCtrl", function ($scope) {
    $scope.someArray = [
        {type:"type1",title:"lorem"},
        {type:"type2",title:"ipsum"},
        {type:"type2",title:"dolor"}
    ];
});
app.directive("genericdirective", function(){
    return{
        restrict: "C",
        template: "<div class='{{obj.type}}'>genericdirective</div>"
    };
});
app.directive("type1", function(){
    return{
        restrict: "C",
        template: "<div>type1</div>"
    };
});
app.directive("type2", function(){
    return{
        restrict: "C",
        template: "<div>type2</div>",
    };
});

Output HTML

<div class="genericdirective ng-scope" ng-repeat="obj in someArray">
    <!-- Not replaced by the actual directive -->
    <div class="type1">genericdirective</div>
</div>
<div class="genericdirective ng-scope" ng-repeat="obj in someArray">
    <!-- Not replaced by the actual directive -->
    <div class="type2">genericdirective</div>
</div>
<div class="genericdirective ng-scope" ng-repeat="obj in someArray">
    <!-- Not replaced by the actual directive -->
    <div class="type2">genericdirective</div>
</div>

Any idea why these are not replaced by the actual directives?

JMaylin
  • 1,378
  • 4
  • 15
  • 38

2 Answers2

2

By using the return in your genericDirective:

app.directive("genericdirective", function(){
    return{
        restrict: "C",
        template: "<div class='{{obj.type}}'>genericdirective</div>"
    };
});

You are returning the link function. The link phase happens after the compile phase. So, by the time you are resolving this template, angular cannot "compile in" your child directives and then link them.

You need to define a compile function and set up the directive at that time in order to modify the html that angular will consider. Any time that you need to manipulate the html before linking the $scope, you probably are wanting to make changes during the compile phase.

To read more about compile and link see the docs here. The section titled "Compilation process, and directive matching" is very helpful.

Davin Tryon
  • 66,517
  • 15
  • 143
  • 132
  • 2
    you can actually compile in the link function, which let you access to the scope, and your obj.type value directly, by injecting $compile in your directive, I made a quick example here : http://jsfiddle.net/DotDotDot/PGMZH/3/ – DotDotDot Oct 02 '13 at 08:58
  • Thank you for the example, it works perfectly, I don't need to read the documentation anymore (well, I'm going to read it just in case ^^). – JMaylin Oct 02 '13 at 09:16
  • 1
    Matter of fact, directive developer guide is something that you would have to read again n again. – Chandermani Oct 02 '13 at 09:27
2

Building on Davin's answer, if you change your directive to this it should work:

app.directive("genericdirective", function($compile){
    return{
        restrict: "C",
        link: function (scope, element, attrs) {
           element.append('<div class="' + scope.obj.type + '">genericdirective</div>');
           $compile(element.contents())(scope);
        }
     };
});
Stevo
  • 2,601
  • 3
  • 24
  • 32
  • 1
    I've selected Davin's answer because he posted an example in the comments, but thank you for your answer. – JMaylin Oct 02 '13 at 09:19