Nested directives don't work as expected

2019-09-13 20:58发布

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?

2条回答
我欲成王,谁敢阻挡
2楼-- · 2019-09-13 21:07

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.

查看更多
Fickle 薄情
3楼-- · 2019-09-13 21:30

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);
        }
     };
});
查看更多
登录 后发表回答