3

I'm trying to chain two nested directives that both use isolated scopes.

<div ng-controller="myController">
    <my-dir on-done="done()">
        <my-dir2 on-done="done()">
        </my-dir2>
    </my-dir>  
</div>

I would like the second directive (my-dir2) to call the done() function of the first directive (my-dir) which in turn would call the controller one.

Unfortunately I don't know how to make the second directive access the callback of the first directive (so far the second directive is looking inside the high level controller, bypassing the first directive).

I think one could possibly make use of "require" but I can't since the two directives are not related (I want to use my-dir2 inside other directives not only my-dir).

To make it clear : I don't want to use require because it means that there would be a dependency of myDir on myDir2. My point is : I want to be able to reuse myDir2 inside others directives. So I don't want myDir2 to be based on myDir but I do want to inform the upper directive (myDir) when something is done (like in a callback in js).

I have made a plunker : as you can see in the javascript console, my-dir2 is calling directly the done function from the high level controller.

Does anyone has a clean way to deal with that kind of situation ?

Thanks

nlko
  • 500
  • 1
  • 6
  • 9

2 Answers2

0

Update:

to be able write directives that are independent of each other you need to use events:

  1. use $emit('myEvent', 'myData') to fire an event that will be handled by scopes that are upward in the hierarchy.
  2. use $broadcast('myEvent', 'myData') to fire an event that will be handled by scopes that are downward in the hierarchy.
  3. to handle the event that was fired by $emit or $broadcast use $on('myEvent', function(event, data){\\your code})

P.S.: in your case the $emit won't work because both directives scopes are on the same level in the hierarchy so you will need to use $rootScope.$broadcast('myEvent' \*, myData*\); I've updated my plunker to reflect the needed changes http://plnkr.co/edit/eTkO6sk6hpuYPnCjlSKn?p=info

The following will make inner directive dependent on the outer directive:

basically to be able to call a function in the first directive you need to do some changes:

  1. add require = '^myDir' to myDir2
  2. remove the onDone from myDir2 and keep the isolated scope scope:{}
  3. add controller parameter to link function in myDir2 link: function(scope,element,attrs,controller)
  4. in myDir1 controller change the definition of the done function from $scope.done to this.done
  5. call controller.done() in myDir2

here is a plunker with the needed changes http://plnkr.co/edit/eTkO6sk6hpuYPnCjlSKn

  • Thanks for your help, unfortunately as I said, I don't want to use require because it means that there would be a dependency of myDir on myDir2. My point is : I want to be able to reuse myDir2 inside others directives. So I don't want myDir2 to be based on myDir but I do want to inform the upper directive when something is done. – nlko Oct 13 '14 at 18:45
  • 1
    @nlko you can use events as a mean of communication between directives, check this answer http://stackoverflow.com/a/14502755/158421 it explains the concept in controllers which can be applied to directives too – Mohammad Shahrouri Oct 23 '14 at 09:59
  • Thanks Mohammad for pointing me out this. I think the third solution (emitting an event from the child to the parent where the parent is free to catch it) seems to suit my need. I give you a point (if you prefer create a new answer)! – nlko Nov 01 '14 at 10:52
0

I think you can do something like these: angular.element('my-dir').controller('myDir').done();

give a try!

airton
  • 1
  • 1