如何访问未使用模板的指令中的隔离范围

时间:2016-10-27 23:15:36

标签: javascript angularjs angularjs-scope

当我在元素上设置控制器时,该元素及其子元素可以访问该控制器的范围。这是有道理的。

但是,当我向一个元素(作为属性)添加一个带有隔离范围的指令时,我希望该元素及其子元素可以访问隔离范围,但它们不会。

HTML:

<body ng-app="testMod" ng-controller="ParentController">
  <div id="div1" ng-controller="MyController">
    <a href="#" ng-click="doit()">MyController</a>
  </div>
  <div id="div2" my-directive>
    <a href="#" ng-click="doit()">MyDirective</a>
  </div>
</body>

JS:

(function() {
  angular
    .module('testMod', [])
    .controller('ParentController', ['$scope', function($scope) {
      $scope.doit = function() {
        console.log('ParentController scope')
      }
    }])
    .directive('myDirective', [function() {
      return {
        scope: {},
        restrict: 'A',
        controller: 'MyController'
      };
    }])
    .controller('MyController', ['$scope', function($scope) {
      $scope.doit = function() {
        console.log("MyController scope");
      };
    }]);
})();

当我点击#div1的链接时,会输出MyController scope,正如我所料。

当我点击#div2的链接时,由于我在指令中添加了隔离范围,我希望相同,但输出ParentController scope

那么,使用隔离范围的元素是什么?它适用于什么?我可以让div[my-directive]的孩子以某种方式访问​​它吗?

Transclude对我没有帮助;我希望div[my-directive]的孩子能够访问指令的隔离范围,而不是父范围,但在这种情况下我不能使用模板。我基本上希望来自#div1的控制器行为,但是我需要一个link函数来对子节点进行一些DOM操作。

1 个答案:

答案 0 :(得分:0)

我找到了答案。我会在这里解释,以防将来帮助某人。

答案是使用transclusion,并使用transclude()函数将元素的内容绑定到隔离范围。这可以通过在指令对象上设置transclude: true并使用链接函数调用transclude()来完成,如下所示:

(function() {
  angular
    .module('testMod', [])
    .controller('ParentController', ['$scope', function($scope) {
      $scope.doit = function() {
        console.log('ParentController scope')
      }
    }])
    .directive('myDirective', [function() {
      function link(scope, element, attrs, ctrl, transclude) {
          transclude(scope, function(clone) {
          element.append(clone);
        });    
      }
      return {
        link: link,
        scope: {},
        transclude: true,
        restrict: 'A',
        controller: 'MyController'
      };
    }])
    .controller('MyController', ['$scope', function($scope) {
      $scope.doit = function() {
        console.log("MyController scope");
      };
    }]);
})();

我是如何理解这一点的,当你在范围上设置transclude: true时,Angular会从DOM中删除元素的内容。使用模板时,您可以使用模板中某处的ng-transclude属性来告诉Angular在哪里插入内容,这是我对翻译的有限理解的结束(正如我从Angular's Developer's Guide中提到的那样)。

在这种情况下,我们没有使用模板,因此ngTransclude不是一个选项,而且我们想要绑定到隔离范围,而不是内容的原始范围(父范围)。但是我们可以使用Angular为transclude()函数提供的link()函数来手动设置它,将提取的DOM内容绑定到隔离的范围。

This question给了我答案,我发现this section Angular文档有助于准确理解我在做什么。

我创建了jsfiddle来玩这个。