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.
AngularJS applications cannot be nested within each other. Do not use a directive that uses transclusion on the same element as ngApp . This includes directives such as ngIf , ngInclude and ngView .
The ng-transclude directive facilitates AngularJS to capture everything that is put inside the directive in the markup and use it somewhere in the directive's template.
The ngRef attribute tells AngularJS to assign the controller of a component (or a directive) to the given property in the current scope. It is also possible to add the jqlite-wrapped DOM element to the scope. The ngRepeat directive instantiates a template once per item from a collection.
Note: When you create a directive, it is restricted to attribute and elements only by default. In order to create directives that are triggered by class name, you need to use the restrict option. The restrict option is typically set to: 'A' - only matches attribute name.
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>',
compile: 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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With