2016-11-07 70 views
0

这是一个真正问题的简化版本,但我想了解正在发生的情况以及如何解决该问题。我有一个指令,应该加载不同的模板depennding在参数绑定到它。Angular指令动态模板不与绑定一起使用

var app = angular.module('my_app', []) 
 
    .controller('controller', Controller) 
 
    .directive('dirTwo', DirTwo); 
 

 
function Controller() { 
 
    var este = this; 
 
    this.list = ["number", "text", "text"]; 
 
    this.change = function() { 
 
    this.list = this.list.reverse(); 
 
    } 
 
} 
 

 
function DirTwo() { 
 
    return { 
 
    restrict: 'E', 
 
    //template: ' Name: {{name}}{{type}}', 
 
    template: my_template, 
 
    scope: { 
 
     type: "=" 
 
    }, 
 
    link: function($scope) { 
 
     $scope.name = "Pepito"; 
 
     console.log("scope type: " + $scope.type); 
 
    } 
 
    } 
 
} 
 
var my_template = function(elem, attrs, $scope) { 
 
    console.log("template type: " + attrs.type); 
 
    switch (attrs.type) { 
 
    case 'number': 
 
     return '<a href="#">{{type}}</a>'; 
 
     break; 
 
    default: 
 
     return ' ---- ' 
 
     break; 
 
    } 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script> 
 
<div class="app" ng-app="my_app" ng-controller="controller as App"> 
 
    <p>{{App.list}} 
 
    <button ng-click="App.change()">Reverse</button> 
 
    </p> 
 
    <dir-two ng-repeat="item in App.list track by $index" type="item"></dir-two> 
 
</div>

日志中的模板函数打印字item而不是numbertext。我如何解决它以正确加载模板?

+0

尝试'type =“{{item}}”'? – GillesC

+0

@GillesC,试过了,错误更大!事实上,你会发现绑定在链接函数中工作,但不在模板中。 – Vandervals

回答

1

不幸的是,没有办法像这样使用template,因为模板解析发生在编译阶段之前,您的type将假定范围值。要根据范围值更改指令的模板,您必须观察该值并在指令元素发生更改时重新编译。它将使用新模板重新编译该指令,但具有相同的范围。你可以这样做一次(即没有0​​)。

以下代码片段实现了此解决方案。

var app = angular.module('my_app', []) 
 
    .controller('controller', Controller) 
 
    .directive('dirTwo', DirTwo); 
 

 
function Controller() { 
 
    var este = this; 
 
    this.list = ["number", "text", "text"]; 
 
    this.change = function() { 
 
    this.list = this.list.reverse(); 
 
    } 
 
} 
 

 
function DirTwo($compile) { 
 
    return { 
 
    restrict: 'E', 
 
    template: '', 
 
    scope: { 
 
     type: "=" 
 
    }, 
 
    link: function(scope, element) { 
 
     
 
     var tmplScope; 
 
     
 
     scope.name = "Pepito"; 
 
     scope.$watch('type', function(type) { 
 

 
     if (tmplScope) tmplScope.$destroy(); 
 

 
     tmplScope = scope.$new(); 
 

 
     element.html(getTemplate(type)); 
 
     $compile(element.contents())(tmplScope); 
 
     }); 
 
    } 
 
    } 
 
} 
 
var getTemplate = function(type) { 
 

 
    switch (type) { 
 
    case 'number': 
 
     return '<a href="#">{{type}}</a>'; 
 
     break; 
 
    default: 
 
     return ' ---- ' 
 
     break; 
 
    } 
 
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.1/angular.min.js"></script> 
 
<div class="app" ng-app="my_app" ng-controller="controller as App"> 
 
    <p>{{App.list}} 
 
    <button ng-click="App.change()">Reverse</button> 
 
    </p> 
 
    <dir-two ng-repeat="item in App.list track by $index" type="item"></dir-two> 
 
</div>

更新注意:我已经改变了实际的编译系统每次被编译时间来创建一个新的子范围,也当它被重新编译打掉这个孩子范围防止在重新编译时添加新的watchers而不放弃先前的版本。感谢@georgeawg在评论中警告了这个问题。

+0

请注意,重新编译模板会导致内存泄漏。每个新模板都会向观察者添加观察者。 – georgeawg

+1

@georgeawg你是对的先生!我没有注意到这一点。我首先想到它会被编译一次,所以根本不是问题。但是,在重新编译时,范围正在创建新的观察者并保留旧的观察者,潜在性会在一定数量的重新编译时产生内存泄漏。谢谢你为我们指出这一点,好的观察。我也更新了我的答案。 –