不带指令范围的转换指令,即使具体告知

时间:2015-05-23 02:05:36

标签: javascript angularjs

我正在使用一个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”,我不知道如何强制转换代码的范围使用我在控制器中设置的范围。

2 个答案:

答案 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”参数已被弃用在作用域继承时根本不起作用。但是,它有,而且我不确定它是否是一个错误或功能。