Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS - $emit only works within it's current scope?

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

like image 416
Intellix Avatar asked Mar 21 '23 19:03

Intellix


2 Answers

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!")
like image 131
Ilan Frumer Avatar answered Apr 01 '23 21:04

Ilan Frumer


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

like image 45
GRaAL Avatar answered Apr 01 '23 19:04

GRaAL