4

Preface

When I declare a directive under a controller, e.g.

<div ng-controller="MyController">
  <my-directive></my-directive>
</div>

the directive inherits that controller's scope by default. This means if the controller defines

$scope.Heaven = "Free Beer"

then I have access to that within the directive's template via

{{ Heaven }}

Question

When declaring a directive within another directive, why doesn't the child inherit scope like it would if placed in a controller?

<my-parent-directive>
  <my-child-directive>
  </my-child-directive>
</my-parent-directive>

In short, if I declare a controller function for my-parent-directive and in it write:

$scope.Heaven = "Free Beer"

My child directive doesn't have access to this by default. Why is that? (This assumes "scope: true" within the parent, no scope declaration in the child, and the child requiring the parent via "require: 'my-parent-directive')

Example codepens:

Directive wrapped in controller
Directive wrapped in directive

Question was modified after answer was given - the below is to preserve the reference
Directive wrapped in directive old

7
  • it does if you try it with $scope.abc.Heaven Commented Dec 6, 2014 at 17:29
  • How would I access that in the child directive? Commented Dec 6, 2014 at 17:34
  • {{abc.Heaven}}, just like every other variable Commented Dec 6, 2014 at 17:39
  • Oh you mean like this? codepen.io/anon/pen/gbPLZY?editors=101 Because that doesn't work Commented Dec 6, 2014 at 17:41
  • possible duplicate of Access Parent Scope in Transcluded Directive Commented Dec 6, 2014 at 18:01

1 Answer 1

5

I am looking at the "Directive wrapped in directive old" on codepen. I think it is this you want to fix, but I'm not certain since your codepen is different to the example in your question (that's not a criticism, just clarification in case I am heading down the wrong route for you!)

However, if I am correct (and I am referring to the "Directive wrapped in directive old" on codepen for the rest of this answer):

You have declared the scope in myWrapper to be inherited ("scope: true"), therefore any properties that you add to the scope within myWrapper (such as "$scope.passdown = $attrs.passdown;") will only be visible to myWrapper.

You can remove the "scope: true" from myWrapper to share the scope between everything (not a great structure to use, but it will work) and you will solve your immediate problem, if I have understood you correctly. Or you can move the "passdown" property to a mutable object on the "parent" controller "$scope.abc = {passdown: ''};" for example. Then modify the value in myWrapper: "$scope.abc.passdown = $attrs.passdown;" and access it as "abc.passdown" in your interpolated expressions.

a bit of background:

changes to immutable types in "child" controllers/directive will make a copy of the property and those changes will never be seen on any other scope.

No scope declaration means shared scope - all components that share this scope too can see any properties / changes (to mutables) made on the scope. Tends to end up with closely coupled components that become very difficult to maintain.

"scope: true" means inherited scope and any additions made to the scope will only be visible to the inherting scope (ie the "child"). Changes to mutable properties in the parent will be visible to all other components that share this scope.

"scope: {...}" creates an isolated scope and provides a safe way to expose properties to parents and let the children modify those properties. This implementation is more work but you will end up with code that is easier to understand, maintain and share.

I hope this answer isn't too rambling and it helps you solve your problem.

Sign up to request clarification or add additional context in comments.

8 Comments

Totally agree , the demo and question should have same code! Issue gets all muddled up discussing totally different variables
Yeah - Apparently my google keywords were lacking, because the root of my problem is that "transclusion: true" and "scope: true" both create their own scopes (according to stackoverflow.com/a/16868935/984407) I didn't realize that and now I'm starting to understand my issue a little more. What you say makes more sense to me after reading that answer, and I appreciate your 'background' section because I'm really having trouble learning this stuff.
That's great - glad I could help. Post some more questions here if you want to know more. Just remember that scope has three "states": shared, inherited and isolated. Once you've got those straight you should be good on this point, I think.
@charlietfl - I apologize for that, I'll fix it now. Basically I have to remove the parent controller, but I thought the concepts were the same
@PhilOlson your question should be self contained, then any demo should be a representation of the question
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.