隔离范围也用于嵌入?

Isoleted scope also for transclude?

我想在我的其他指令中添加我的自定义指令。 第二个指令应该使用第一个指令的范围。 问题是第一个指令具有独立的范围,显然它也被第二个指令隔离,我认为它不应该因为我使用的是 transclude。

这里是例子。当我评论 scope: {test:"@"} 时,一切正常。 如何解决?

angular.module("myApp", [])
            .controller("initCtrl", function ($scope) {

            });
    angular.module('myApp')
            .directive('firstDirective', ['$timeout', function ($timeout) {
                return {
                    restrict: 'E',
                    scope: {test: "@"}, //everything is OK when I comment that.
                    transclude: true,
                    template: '<div> First Directive {{myVar}} {{test}}<div ng-transclude></div></div>',
                    controller: "firstDirectiveCtrl",
                    link: function (scope, element, attributes) {

                    }
                };
            }])
            .controller("firstDirectiveCtrl", ['$scope', '$timeout', function ($scope, $timeout) {
                $scope.myVar = "Var from first directive";
                $timeout(function () {
                    $scope.myVar = "Var from first directive has changed";
                }, 1000);
            }])
            .directive('secondDirective', [function () {
                return {
                    restrict: 'E',
                    scope: false,
                    require: "^firstDirective",
                    template: '<div> Second Directive {{myVar}}</div>',
                    link: function (scope, element, attributes) {
                        //scope.myVar = "Var from second directive";
                    }
                };
            }]);
<!DOCTYPE html>
<html data-ng-app="myApp">
<head lang="en">
    <meta charset="UTF-8">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <title></title>
</head>
<body>
<div ng-controller="initCtrl" class="container">
    <first-directive test="test">
        <second-directive></second-directive>
        {{myVar}} 
<br><i>no var unless I comment scope: {test:"@"} i first directive.</i>
    </first-directive>
</div>
</body>
</html>

因为第一个指令使用独立作用域,所以 myVar 在指令模板中不可见。 myVar 在嵌入的内容中可见,因为它链接到嵌入范围,这是父控制器范围的子范围。包含作用域和 firstDirective 的独立作用域是姊妹作用域 - 但彼此分开。

注意:这仅适用于 1.2+。在 1.3 中,事情似乎发生了变化,包含作用域是链中上一个作用域的子作用域。

要解决这个问题,您只需将 myVar 传递给您的隔离范围:

.directive('firstDirective', ['$timeout', function ($timeout) {
    return {
        restrict: 'E',
        scope: {test: "@", myVar: "="}, //pass myVar into your isolated scope.
        transclude: true,
        template: '<div> First Directive {{myVar}} {{test}}<div ng-transclude></div></div>',
        controller: "firstDirectiveCtrl",
        link: function (scope, element, attributes) {

        }
    };
}])

HTML

<div ng-controller="initCtrl" class="container">
    <first-directive test="test" my-var="myVar">
        <second-directive></second-directive>
        {{myVar}} 
        ...
    </first-directive>
</div>

angular.module("myApp", [])
            .controller("initCtrl", function ($scope) {

            });
    angular.module('myApp')
            .directive('firstDirective', ['$timeout', function ($timeout) {
                return {
                    restrict: 'E',
                    scope: {test: "@", myVar:"="}, //everything is OK when I comment that.
                    transclude: true,
                    template: '<div> First Directive {{myVar}} {{test}}<div ng-transclude></div></div>',
                    controller: "firstDirectiveCtrl",
                    link: function (scope, element, attributes) {

                    }
                };
            }])
            .controller("firstDirectiveCtrl", ['$scope', '$timeout', function ($scope, $timeout) {
                $scope.myVar = "Var from first directive";
                $timeout(function () {
                    $scope.myVar = "Var from first directive has changed";
                }, 1000);
            }])
            .directive('secondDirective', [function () {
                return {
                    restrict: 'E',
                    scope: false,
                    require: "^firstDirective",
                    template: '<div> Second Directive {{myVar}}</div>',
                    link: function (scope, element, attributes) {
                        //scope.myVar = "Var from second directive";
                    }
                };
            }]);
<!DOCTYPE html>
<html data-ng-app="myApp">
<head lang="en">
    <meta charset="UTF-8">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
    <title></title>
</head>
<body>
<div ng-controller="initCtrl" class="container">
    <first-directive test="test" my-var="myVar">
        <second-directive></second-directive>
        {{myVar}} 
<br><i>no var unless I comment scope: {test:"@"} i first directive.</i>
    </first-directive>
</div>
</body>
</html>

您可以访问 $parent 范围 ex。 $parent.myVar。 仅适用于 angular 1.3

angular.module("myApp", [])
            .controller("initCtrl", function ($scope) {

            });
    angular.module('myApp')
            .directive('firstDirective', ['$timeout', function ($timeout) {
                return {
                    restrict: 'E',
                    scope: {
                        test:"@",
                        //myVar:"="
                    },
                    transclude: true,
                    template: '<div> First Directive {{myVar}} {{test}}<div ng-transclude></div></div>',
                    controller: "firstDirectiveCtrl",
                    link: function (scope, element, attributes) {

                    }
                };
            }])
            .controller("firstDirectiveCtrl", ['$scope', '$timeout', function ($scope, $timeout) {
                $scope.myVar = "Var from first directive";
                $timeout(function () {
                    $scope.myVar = "Var from first directive has changed";
                }, 1000);
                this.getMyVar = function () {
                    return $scope.myVar;
                };
                //console.log($scope.getMyVar());
            }])
            .directive('secondDirective', [function () {
                return {
                    restrict: 'E',
                    scope: false,
                    require: "^firstDirective",
                    template: '<div> Second Directive {{$parent.myVar}}</div>',
                    link: function (scope, element, attributes, ctrl) {
                        //console.log(scope.$parent);
                        //console.log(ctrl);
//                        console.log(ctrl.myVar);
//                        console.log(ctrl.getMyVar());
                        //scope.myVar = "Var from second directive";
                    }
                };
            }]);
<!DOCTYPE html>
<html data-ng-app="myApp">
<head lang="en">
    <meta charset="UTF-8">
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.8/angular.min.js"></script>
    <title></title>
</head>
<body>
<div ng-controller="initCtrl" class="container">
    <first-directive test="test">
        {{$parent.myVar}}
        <second-directive></second-directive>
    </first-directive>
</div>
</body>
</html>