【问题标题】:Access Parent Scope in Transcluded Directive嵌入指令中的访问父范围
【发布时间】:2013-05-31 22:09:13
【问题描述】:

我想访问父指令的范围,但我似乎无法获得正确的设置组合。这可能吗?这是正确的方法吗?

我真的想避免在 MyCtrl 中放置 SOME_CONST(这将有助于我通过控制流进行 DOM 更新)之类的东西

<div ng-controller="MyCtrl">
    <parent>
        <child></child>
    </parent>
</div>

var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
    $scope.obj = {prop:'foo'};
}

myApp.directive('parent', function() {
    return {
        scope: true,
        transclude: true,
        restrict: 'EA',
        template: '<div ng-transclude><h1>I\'m parent {{obj.prop}}<h1></div>',
        link: function(scope, elem, attrs) {
            scope.SOME_CONST = 'someConst';
        }
    }
});

myApp.directive('child', function() {
    return {
        restrict: 'EA',
        template: '<h1>I\'m child.... I want to access my parent\'s stuff, but I can\'t.  I can access MyCtrlScope though, see <b>{{obj.prop}}</b></h1> how can I access the <b>SOME_CONST</b> value in my parent\'s link function?  is this even a good idea? {{SOME_CONST}}.  I really don\'t want to put everything inside the MyCtrl',
    }
});

请看这个fiddle

谢谢

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-scope


    【解决方案1】:

    使用transclude: true 和scope: true,parent 指令创建了两个新范围:

    范围 004 是 scope: true 的结果,范围 005 是 transclude: true 的结果。由于child 指令不会创建新范围,因此它使用转入范围 005。从图中可以看出,没有从范围 005 到范围 004 的路径(通过私有属性 $$prevSibling 除外,它正好相反$$nextSibling 的方向——但不要使用这些。)

    @joakimbl 的解决方案在这里可能是最好的,尽管我认为在父指令的控制器上定义 API 比在 this 上定义属性更常见:

    controller: function($scope) {
        $scope.SOME_CONST = 'someConst';
        this.getConst = function() {
           return $scope.SOME_CONST;
        }
    }
    

    然后在child指令中:

    link:function(scope,element,attrs,parentCtrl){
        scope.SOME_CONST = parentCtrl.getConst();
    },
    

    这就是 tabs 和 pane 指令在 Angular 主页上的工作方式(“创建组件”示例)。

    【讨论】:

    • @Mark Rajcok - 很好的回答马克,你似乎是这个网站上为数不多的真正完全理解 Angular 的人之一。我有一个与此类似的问题,但在此链接:link。我的问题是,当链接方法在子指令上运行时,子指令的模板已经被渲染。这意味着我不能在渲染之前使用子属性中的父属性来设置范围变量。
    • 这很好,但似乎这个值是复制而不是绑定(即双向数据绑定)
    • 同意,这不是双向数据绑定。要回答最初的问题,子控制器只需要访问 scope.$parent 就可以了,它具有继承和双向数据绑定的好处。
    • 这是一个很棒的干净的答案。
    【解决方案2】:

    通常,您在指令中访问父范围变量的方式是通过双向绑定(scope:{model:'=model'} - 请参阅指令配置中的the angular guide on directives),但由于您使用的是嵌入,所以这不是那么简单.如果子指令始终是父指令的子指令,您可以将其配置为需要父指令,然后在子链接函数中访问父控制器:

    myApp.directive('parent', function() {
      return {
        scope: true,
        transclude: true,
        restrict: 'EA',
        template: '<div ng-transclude><h1>I\'m parent {{obj.prop}}<h1></div>',
        controller: function($scope) {
            $scope.SOME_CONST = 'someConst';
            this.SOME_CONST = $scope.SOME_CONST;
        }
      }
    });
    
    myApp.directive('child', function() {
      return {
        restrict: 'EA',
        require:'^parent',
        scope:true,
        link:function(scope,element,attrs,parentCtrl){
            scope.SOME_CONST = parentCtrl.SOME_CONST;
        },
        template: '<h1>I\'m child.... I want to access my parent\'s stuff, but I can\'t.  I can access MyCtrlScope though, see <b>{{obj.prop}}</b></h1> how can I access the <b>SOME_CONST</b> value in my parent\'s link function?  is this even a good idea? {{SOME_CONST}}.  I really don\'t want to put everything inside the MyCtrl',
      }
    });
    

    查看此更新:http://jsfiddle.net/uN2uv/

    【讨论】:

      【解决方案3】:

      我刚遇到同样的问题,最后用角度手册解决了;)

      简而言之:您需要在您的 parent 指令中使用 控制器 并且 要求 该控制器 在 您的子指令。这样你就可以得到你的父属性。

      见https://docs.angularjs.org/guide/directive 章节:创建可通信的指令

      我将您的小提琴更改为使用控制器,现在您可以访问您的常量: https://jsfiddle.net/bbrqdmt3/1/

      var myApp = angular.module('myApp',[]);
      
      function MyCtrl($scope) {
          $scope.obj = {prop:'foo'};
      }
      
      myApp.directive('parent', function() {
          return {
              scope: true,
              transclude: true,
              restrict: 'EA',
              template: '<div ng-transclude><h1>I\'m parent {{obj.prop}}<h1></div>',
              controller: function($scope) {
                  this.getConst= function() {
                      return 'someConst';
                  }                        
              },
          }
      });
      
      myApp.directive('child', function() {
          return {
              restrict: 'EA',
              require : '^parent',
              link: function(scope, element, attrs, ctrl) {
                  scope.value= ctrl.getConst();
              },
              template: '<h1>I\'m child.... I want to access my parent\'s stuff, but I can\'t.  I can access MyCtrlScope though, see <b>{{obj.prop}}</b></h1> how can I access the <b>SOME_CONST</b> value in my parent\'s link function?  is this even a good idea? {{value}}.  I really don\'t want to put everything inside the MyCtrl',
          }
      });
      

      【讨论】:

        【解决方案4】:

        控制器后面的链接fn的参数中有一个transclude fn。

        myApp.directive('parent', function() {
          return {
            scope: true,
            transclude: true,
            restrict: 'EA',
            template: '<div><h1>I'm a parent header.</h1></div>',
            link: function (scope, el, attrs, ctrl, transclude) {
        
                transclude(scope, function (clone, scope) {
                    element.append(clone); // <-- will transclude it's own scope
                });
        
            },
            controller: function($scope) {
                $scope.parent = {
                    binding: 'I\'m a parent binding'
                };
            }
          }
        });
        
        myApp.directive('child', function() {
          return {
            restrict: 'EA',
            require:'^parent',
            scope:true,
            link:function(scope,element,attrs,parentCtrl){
        
            },
            template: '<div>{{parent.binding}}</div>' // <-- has access to parent's scope
          }
        });
        

        【讨论】:

          猜你喜欢
          • 2013-08-06
          • 2013-05-22
          • 2016-05-19
          • 2014-09-06
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多