嵌套指令和父作用域

时间:2013-09-26 11:01:29

标签: angularjs angularjs-directive angularjs-scope

我遇到的问题可以在http://jsfiddle.net/miketheanimal/2CcYp/13/看到。这将我的问题降到最低。

我有一个控制器“main”,一个转换directive的指令“outer”和一个没有的指令“inner”。每个指令都有一个隔离范围和一个控制器。主要和指令控制器设置$ scope._name ='...'所以我可以区分它们。

var module = angular.module('miketa', []);
function main ($scope) {
    $scope._name = 'main' ;
} ;
module.directive('outer', function() {
    return {
        restrict: 'E',
        replace: true,
        transclude: true,
        scope: {},
        template: '<div><div ng-transclude></div></div>',
        controller: [ '$scope', function($scope) {
            $scope._name = 'outer' ;
            document.getElementById('opn').innerHTML = $scope.$parent._name ;
        }]}});
module.directive('inner', function() {
    return {
        restrict: 'E',
        replace: true,
        scope: {},
        template: '<div></div>',
        controller: [ '$scope', function($scope) {
            $scope._name = 'inner' ;
            document.getElementById('ipn').innerHTML = $scope.$parent._name ;
        }]}});

HTML将这些作为主要内容 - &gt;外 - &gt;内。指令中的控制器函数将其范围名称(即,* $ scope。$ parent._name)复制到呈现的HTML中(直接操纵DOM的道歉,这是最简单的显示方式)名字!)。

我希望外部显示来自控制器的名称(即,“main”),并且我希望 inner 显示名称从外部(即,“外部”),这不是,而是显示“主”。

问题实际上表明了自己,因为在实际代码中,我想绑定内部外部范围,但内部最终绑定到范围。

1 个答案:

答案 0 :(得分:9)

事实上,它不是一个错误,它是理想的行为。来自docs on the $compile service

  

在典型的设置中,窗口小部件创建了一个隔离范围,但是   transclusion不是一个孩子,而是一个孤立范围的兄弟。这个   使得窗口小部件可以具有私有状态,以及   转换为绑定到父(预隔离)范围。

另请参阅:Why ng-transclude's scope is not a child of its directive's scope - if the directive has an isolated scope?

如果你确实需要让它工作,请忘记ng-transclude并执行:

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

function main($scope) {
    $scope._name = 'main';
};
module.directive('outer', function () {
    return {
        restrict: 'E',
        replace: true,
        scope: {},
        template: '<div><inner></inner></div>',
        controller: ['$scope', function ($scope) {
            $scope._name = 'outer';
            document.getElementById('opn').innerHTML = $scope.$parent._name;
        }]
    }
});
module.directive('inner', function () {
    return {
        restrict: 'E',
        replace: true,
        scope: {},
        template: '<div></div>',
        controller: ['$scope', function ($scope) {
            $scope._name = 'inner';
            document.getElementById('ipn').innerHTML = $scope.$parent._name;
        }]
    }
});

瞧!它有效。