我正在使用一个transcluding指令,它本身正在使用一个控制器,它应该重新定义内部范围,但不是。无论我使用了多少技巧,我似乎无法完成这项工作(让我相信我做错了什么)。
代码简化为一个简单的案例,如下所示:
HTML:
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="http://cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.min.js"></script>
</head>
<body ng-controller="MainCtrl">
<mydirective>
{{foo}}
</mydirective>
</body>
</html>
JavaScript的:
angular.module('app', [])
.controller('MainCtrl', function($scope) {
$scope.foo = 'bar';
})
.controller('InDirectiveController', function($scope) {
$scope.foo = 'baz';
})
.directive('mydirective', function() {
return {
restrict: 'EA',
scope: false,
template:'<div ng-controller="InDirectiveController">'+
'{{foo}} <inside></inside>'+
'</div>',
transclude:true,
link: function(scope, element, attrs, ctrl, transclude) {
transclude(scope, function(clone, scope) {
element.find("inside").append(clone);
});
}
};
});
此处示例
http://jsbin.com/wuqoqalenu/1/edit?html,js,output
我希望输出为“baz baz”,因为我特意使用了transclude函数。但是,它实际上是“baz bar”,我不知道如何强制转换代码的范围使用我在控制器中设置的范围。
答案 0 :(得分:3)
如果没有替换:true,您基本上可以获得指令HTML(编译前)
的以下内容<mydirective>
<div ng-controller="InDirectiveController">
{{foo}} <inside></inside>
</div>
<mydirective>
编译时,指令范围与外部(MainCtrl)范围保持一致,因此将根据该范围评估已转换的内容。因此,第一个{{foo}}是&#34; baz&#34; (来自InDirectiveController),被转换的内容{{foo}}是&#34; bar&#34; (来自MainCtrl)。
使用replace:true,编译的指令HTML变为:
<div ng-controller="InDirectiveController">
{{foo}} <inside></inside>
</div>
当angular编译它时,ng-controller创建一个继承自MainCtrl范围的新范围,该范围与指令的DOM节点相关联,因此它成为指令的范围。因此,当你进行转换时,它现在正在使用InDirectiveController的范围,所以你得到了&#34; baz baz&#34;。
更新以解决评论中的问题:
指令并不总是创建新的范围。当你使用
scope: false
指令范围将与&#34;外部范围&#34;相同。因此,当指令的链接功能运行时,它将是&#34;外部范围&#34;。
transclude函数使用作为第一个参数传递的作用域作为已转换内容的作用域。在您的第一个示例中,此范围是传递给链接函数的范围,在第一种情况下,该范围将是&#34;外部范围&#34;。
当你设置replace:true时,这仍然不会导致创建新的范围。但是,您的模板在其外部元素上使用ng-controller。通过遍历&#34; down&#34;进行角度编译DOM,以及遍历备份的链接。所以它编译指令,然后编译模板,然后链接模板(调用ngController的链接函数,创建一个新的范围),然后指令的链接函数与指令的范围&#39 ; s模板元素,现在是ng-controller创建的范围(而不是&#34;外部范围&#34;)。
更新:没有mg控制器的指令实施
.directive('mydirective', function() {
return {
restrict: 'EA',
scope: true,
controller: function($scope) {
$scope.foo = 'baz';
},
template:'<div>'+
'{{foo}} <inside></inside>'+
'</div>',
transclude:true,
link: function(scope, element, attrs, ctrl, transclude) {
transclude(scope, function(clone, scope) {
element.find("inside").append(clone);
});
}
};
});
答案 1 :(得分:0)
添加replace: true
以某种方式神奇地修复它。
我不知道为什么 ,但确实如此。
此处示例
http://jsbin.com/muhomuxuse/2/edit
编辑:
根据angular documentation,“replace”参数已被弃用且在作用域继承时根本不起作用。但是,它有,而且我不确定它是否是一个错误或功能。