There are numerous methods for communication between directives. For instance, in the case of nested directives where inner directives need to communicate something to the outer directive (e.g., user selection).
<outer>
<inner></inner>
<inner></inner>
</outer>
I have identified 5 different ways to achieve this:
require:
parent directive
The inner
directive can require the outer
directive and access a method on its controller. In the inner
definition:
require: '^outer',
link: function(scope, iElement, iAttrs, outerController) {
// This method can be called within the template using ng-click
$scope.chosen = function() {
outerController.chosen(something);
}
}
And in the outer
directive's controller:
controller: function($scope) {
this.chosen = function(something) {
}
}
$emit
event
The inner
directive can send an event using $emit
, which the outer
directive can then respond to using $on
. In the inner
directive's controller:
controller: function($scope) {
$scope.chosen = function() {
$scope.$emit('inner::chosen', something);
}
}
And in the outer
directive's controller:
controller: function($scope) {
$scope.$on('inner::chosen', function(e, data) {
}
}
Execute expression in parent scope, via &
The item can bind to an expression in the parent scope and execute it when needed. The HTML structure would look like:
<outer>
<inner inner-choose="functionOnOuter(item)"></inner>
<inner inner-choose="functionOnOuter(item)"></inner>
</outer>
Inside the inner
controller, there is an 'innerChoose' function that can be triggered:
scope: {
'innerChoose': '&'
},
controller: function() {
$scope.click = function() {
$scope.innerChoose({item:something});
}
}
This will call the 'functionOnOuter' function on the outer
directive's scope:
controller: function($scope) {
$scope.functionOnOuter = function(item) {
}
}
Scope inheritance on non-isolated scope
In cases of nested controllers with non-isolated scopes, inner directives can directly call functions in the scope chain. Within the inner
directive:
// scope: anything but a hash {}
controller: function() {
$scope.click = function() {
$scope.functionOnOuter(something);
}
}
And in the outer
directive:
controller: function($scope) {
$scope.functionOnOuter = function(item) {
}
}
By service injected into both inner and outer
A service can be injected into both directives, allowing them to access the same object or notify the service by calling functions. They can also register themselves to be notified in a pub/sub system, even if the directives are not nested.
Question: What are the potential advantages and disadvantages of each of these methods over the others?
Credit/Disclaimer: This question was originally found on programmers.SE and was authored by Michal Charemza. The original question can be accessed here.