AngularJS: ng-controller по директиве не работает над включенными элементами в директиве

Здесь находится мой script:

angular.module('MyApp',[])
.directive('mySalutation',function(){
    return {
        restrict:'E',
        scope:true,
        replace:true,
        transclude:true,
        template:'<div>Hello<div ng-transclude></div></div>',
        link:function($scope,$element,$attrs){
        }
    };
})
.controller('SalutationController',['$scope',function($scope){
    $scope.target = "StackOverflow";
}])

и html:

<body ng-app="MyApp">
    <my-salutation ng-controller="SalutationController">
        <strong>{{target}}</strong>        
    </my-salutation>
</body>

Проблема заключается в том, что, когда SalutationController применяется к директиве my-salutation, $scope.target не отображается для передаваемого элемента. Но если я помещаю элемент ng-controller в <body> или на элемент <strong>, он работает. Поскольку docs говорит, ng-controller создает новую область.

  • Кто может объяснить, как этот объем и область действия этой директивы мешают друг другу в этом случае?

  • Как установить контроллер на директиву? Любые подсказки будут оценены.

Ответ 1

1) Задача ng-transclude scope - это область sibling вашей директивы. Когда вы помещаете ng-controller в родительский элемент, область, созданная ng-controller, является родительской областью как вашей директивы, так и ng-transclude. Из-за наследования области, transcluded элемент может привязать {{target}} правильно.

2) Вы можете сделать это, используя пользовательский переход, чтобы связать область видимости

.directive('mySalutation',function(){
    return {
        restrict:'E',
        scope:true,
        replace:true,
        transclude:true,
        template:'<div>Hello<div class="transclude"></div></div>',
        compile: function (element, attr, linker) {
            return function (scope, element, attr) {
                linker(scope, function(clone){
                       element.find(".transclude").append(clone); // add to DOM
                });

            };
        }
    };
})

DEMO

Или используя функцию transclude в функции ссылки:

.directive('mySalutation',function(){
    return {
        restrict:'E',
        scope:true,
        replace:true,
        transclude:true,
        template:'<div>Hello<div class="transclude"></div></div>',
        link: function (scope, element, attr,controller, linker) {
           linker(scope, function(clone){
                  element.find(".transclude").append(clone); // add to DOM
           });
        }
    };
})

DEMO

Ответ 2

Чтобы иметь ту же область действия для директивы и контроллера, вы можете вызвать transcludeFn вручную:

angular.module('MyApp',[])
.directive('mySalutation',function(){
    return {
        restrict:'E',
        scope:true,
        replace:true,
        transclude:true,
        template:'<div>Hello<div class="trans"></div></div>',
        link:function(scope, tElement, iAttrs, controller, transcludeFn){
                console.log(scope.$id);
                transcludeFn(scope, function cloneConnectFn(cElement) {
                    tElement.after(cElement);
                }); 
        }
    };
})
.controller('SalutationController',['$scope',function($scope){
    console.log($scope.$id);
    $scope.target = "StackOverflow";
}]);

plunk

Вы можете видеть, что "003" вызывается каждый раз, и ваш код работает так, как ожидалось, с этой незначительной настройкой.