I am having two custom directives in my angularJS app. One act as a parent and other act as child. I am trying to access parent's scope inside child directive. But I am not getting the desired output.
<div ng-controller="CountryCtrl">
{{myName}}
<div ng-controller="StateCtrl">
<state nameofthestate="'Tamilnadu'">
<city nameofthecity="'Chennai'"></city>
</state>
</div>
</div>
and my script looks like
var app = angular.module("sampleApp",[]);
app.controller("CountryCtrl",function($scope){
$scope.myName = "India";
});
app.controller("StateCtrl",function($scope){
});
app.directive("state",function(){return {
restrict : 'E',
transclude: true,
scope : { myName : '=nameofthestate'},
template:"** {{myName}} is inside {{$parent.myName}}<br/><ng-transclude></ng-transclude>"
}});
app.directive("city",function(){return {
restrict : 'E',
require:'^state',
scope : { myName : '=nameofthecity'},
template:"**** {{myName}} is inside {{$parent.myName}} which is in {{$parent.$parent.myName }}<br/> "
}});
Corresponding JSFiddle available in https://jsbin.com/nozuri/edit?html,js,output
The output which i am getting is
India
** Tamilnadu is inside India
**** Chennai is inside India which is in Tamilnadu
and the expected output is
India
** Tamilnadu is inside India
**** Chennai is inside Tamilnadu which is in India
Can anyone educate me what i am doing wrong here?
You can still access the parent scope using $parent , but this is not normally recommended. Instead, you should specify which parent scope properties (and/or function) the directive needs via additional attributes on the same element where the directive is used, using the = , @ , and & notation.
In a nutshell: You cannot access child scopes from a parent scope. Your solutions: Define properties in parents and access them from children (read the link above) Use a service to share state.
Angular scopes include a variable called $parent (i.e. $scope. $parent ) that refer to the parent scope of a controller. If a controller is at the root of the application, the parent would be the root scope ( $rootScope ). Child controllers can therefore modify the parent scope since they access to it.
Custom directives are used in AngularJS to extend the functionality of HTML. Custom directives are defined using "directive" function. A custom directive simply replaces the element for which it is activated.
The city directive $parent is a transcluded scope of state directive.
The transcluded scope of the state directive is inherit for $parent of state directive which is controller thus that is why $parent.MyName = India.
The $parent of transcluded scope is the state directive isolated scope ( scope = {} ) that is why $parent.$parent.MyName = Tamilnadu ( Part of Angular 1.3 update )
Bit of detail of what happen : How to access parent scope from within a custom directive *with own scope* in AngularJS?
transclude: true - the directive creates a new "transcluded" child scope, which prototypically inherits from the parent scope. If the directive also creates an isolate scope, the transcluded and the isolate scopes are siblings. The $parent property of each scope references the same parent scope.
Angular v1.3 update: If the directive also creates an isolate scope, the transcluded scope is now a child of the isolate scope. The transcluded and isolate scopes are no longer siblings. The $parent property of the transcluded scope now references the isolate scope.
Also Matthew's answer is correct for parent-child directive communications.
Does this work for you? Adapted from this answer.
There isn't a straightforward way to access the transcluded content's parent element, so we inject the parent controller into the child to access its scope.
var app = angular.module('myApp', []);
app.controller("CountryCtrl",function($scope){
$scope.myName = "India";
});
app.controller("StateCtrl",function($scope){
});
app.directive("state",function(){return {
restrict : 'E',
transclude: true,
scope : { myName : '=nameofthestate'},
template:"** {{myName}} is inside {{$parent.myName}}<br/><ng-transclude></ng-transclude>",
controller: function ($scope) {
this.getName = function () {
return $scope.myName;
}
}
}});
app.directive("city",function(){return {
restrict : 'E',
require:'^state',
scope : { myName : '=nameofthecity'},
template:"**** {{myName}} is inside {{parentName}} which is in {{$parent.myName }}<br/> ",
link: function(scope, element, attrs, ctrl) {
scope.parentName = ctrl.getName();
}
}});
When AngularJS encounters transclude , it clones the HTML before replacing it with the template or templateUrl contents. Then, when it encounters ng-transclude , it compiles the transcluded content, but links it to the parent scope instead of the isolated scope of the directive. Thus, the transcluded content still has access to the parent controller and its content, while the directive HTML has an isolated scope (or a new scope, as the case might be).
AngularJS Up and Running
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