4

I've created 2 directives: Parent and Child. Trying to get them to talk to one another. It seems if they both have a scope they don't receive the events. This doesn't seem correct according to the documentation which $emit states: Dispatches an event name upwards through the scope hierarchy notifying the registered ng.$rootScope.Scope#methods_$on listeners.

So surely that should bubble up through scopes?

http://plnkr.co/edit/WNqN4XZKaLAvBEtSyERA?p=preview

2 Answers 2

6

The problem is with you parent/child assumption:

  • Parent is only a parent element of Child but not a parent scope.
  • Actually they are sibling scopes, both children of the $rootScope ($id: 002) in this case.

Why??

  • Due to this commit, Isolate scope is now available only to the isolate directive that requested it and its template.
  • It means that parent directive contents (which included the child directive) are still linked to the outer scope.
  • So the child directive creates isolated scope which is a child of the outer scope.
  • Neither $emit nor $broadcast would work with sibling scopes.

enter image description here


Solution:

here is a plunker: http://plnkr.co/edit/EfKJthkQLitWnF2srykM?p=preview

You can create the child directive as a template of the parent directive, because template directives do get the directive's scope as mentioned above.

.directive('parent', function ($timeout) {
  return {
    template:'<child name="Jimmy"></child>',

do you really need the event bus?

Another solution would be to create a controller on the parent directive and to require it in child directives.

.directive('parent', function ($timeout) {
  return {
    controller: function(){
      this.hungry = function(message){
        // something
      }
    }

child directive:

.directive('child', function ($timeout) {
  return {
    require: "^parent",
    link: function (scope, element, attrs, parentCtrl) {

       parentCtrl.hungry("I'm hungry!")
Sign up to request clarification or add additional context in comments.

2 Comments

Damn, that's quite unexpected. In my mind I was thinking of events like DOM events where they bubble up the DOM. I can imagine many people fall for this trap. The reason I thought events were the solution is because The child doesn't require the parent to function, I wanted to emit events for other directives to listen if they want to know the result of a calculation as they require the child to function for what he knows. I'm guessing I need to pass in data from the outside, alter it and watch inside the parent directive for the change. Thanks for the detailed explanation :)
You can also use require: "?^parent" to optionally require a parent directive's controller. From $compile docs: Attempt to locate the required controller by searching the element's parents or pass null to the link fn if not found.
1

In your example both directives have isolated scopes from the same parent scope, so they do not have parent/child relationship.

To get it work as you expected you may specify scope: true instead of scope: {...}. In this case the scope of child directive will be really child scope of parent directive's scope.

see the plucker

Comments

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.