29

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

我真的很想避免在 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',
    }
});

请看这个小提琴

谢谢

4

4 回答 4

42

使用transclude: trueand 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();
},

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

于 2013-06-01T04:06:47.260 回答
9

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

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/

于 2013-05-31T22:32:42.997 回答
6

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

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

请参阅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',
    }
});
于 2015-04-23T11:09:45.793 回答
0

在控制器之后的链接 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
  }
});
于 2014-11-08T22:04:45.800 回答