最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - AngularJS : ng-controller on directive does not work on transcluded elements within directive - Stack Overflow

programmeradmin1浏览0评论

Here is my 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";
}])

and the html:

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

The problem is , when SalutationController is applied on my-salutation directive, $scope.target is not visible for transcluded element.But if I put ng-controller on <body> or on <strong> element, it works. As docs says, ng-controller creates new scope.

  • Who can explain, how that scope and the scope of the directive are interfering with each other in this case?

  • How can I put controller on directive? Any hints will be appreciated.

Here is my 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";
}])

and the html:

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

The problem is , when SalutationController is applied on my-salutation directive, $scope.target is not visible for transcluded element.But if I put ng-controller on <body> or on <strong> element, it works. As docs says, ng-controller creates new scope.

  • Who can explain, how that scope and the scope of the directive are interfering with each other in this case?

  • How can I put controller on directive? Any hints will be appreciated.

Share Improve this question edited Sep 29, 2015 at 12:17 John Slegers 47.1k23 gold badges204 silver badges173 bronze badges asked Mar 22, 2014 at 8:48 EngineerEngineer 48.8k12 gold badges90 silver badges92 bronze badges 2
  • Is this necessary? Directives can take a controller parameter in the object, in addition to the link parameter. – user677526 Commented Nov 27, 2014 at 19:29
  • @jedd.ahyoung Yes, you can add controller option on directive, but in that case you will have same controller for all directive instances. What if I do not want any controller for my directive, or I need another controller?! – Engineer Commented Nov 28, 2014 at 9:57
Add a ment  | 

2 Answers 2

Reset to default 9

1) The problem is ng-transclude's scope is the sibling scope of your directive. When you put the ng-controller to a parent element, the scope created by ng-controller is parent scope of both your directive and ng-transclude. Due to scope inheritance, the transcluded element is able to bind the {{target}} correctly.

2) You could do that using custom transclusion to bind the scope yourself

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

            };
        }
    };
})

DEMO

Or using the transclude function in the link function:

.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

To have the same scope for the directive, and the controller, you can invoke the transcludeFn manually:

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

You can see that '003' is logged out every time, and your code works as expected with this minor adjustment.

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论