Reputation: 61
I have a two directives
angular.module('myApp.directives', []).
directive('exampleDirective', ['version', function(version) {
return {
link:function(scope,elm,attr) {
elm.on('click',function() {
//access exampleDirective2 behaviour
});
}
}
}]).
directive('exampleDirective2', ['version', function(version) {
return {
link:function(scope,elm,attr) {
elm.on('change',function() {
//access exampleDirective behaviour
});
}
}
}]);
As you can see on exampleDirective elm.on(click) function I want to get the exampleDirective2 function and vice versa.
Is there a way in AngularJS to achieve this?
Upvotes: 1
Views: 389
Reputation: 1676
There are three solutions to this problem:
Share a service between directives, that can contain data and functions.
.service('myService', function(){
this.data = //....
this.function = function() //...
})
.directive('dir1', ['myService', function(myService) {
//...
link: function(scope, elem, attrs) {
scope.data = myService.data;
}
}])
The same for the other directive.
If your directives have a parent/child/sibling relationship:
.directive('dir1', function(){
return {
controller: function(scope, elem, attrs) {
this.sayHello = function() {
alert('hello')
}
}
}
})
.directive('dir2', function(){
return {
require: '^dir1',
link: function(scope, elem, attrs, dir1Ctrl) {
dir1Ctrl.sayHello(); //will alert hello
}
}
})
However, this won't work if you directives have isolated scope. Also, depending on the relationship of the directive (parent/child or siblings) the sintax for the require
attribute changes slightly; you can find more info on the AngularJS docs for directives.
You can also emit/broadcast events from the directive scopes, or inject $rootScope
and use it as an event bus:
.directive('dir1', function($rootScope){
return {
link: function(scope, elem, attrs) {
var emitEvent = function(){
$rootScope.$emit('somethingHappenedEvent', { /*you can pass optional data*/ });
}
emitEvent();
}
}
})
.directive('dir2', function($rootScope) {
return {
link: function(scope, elem, attrs) {
$rootScope.$on('somethingHappenedEvent', function(event) {
if(!event.defaultPrevented) {
//react to event here
}
})
}
}
})
You could also to the same with the normal scope
instead of $rootScope
, but in that case you will have to keep in mind that the event will bubble up/down all the scopes (depending on the use of $emit
or $broadcast
). I prefer to $emit
from $rootScope
, to that it will be the only scope able to catch the event, and will also be quite fast.
Upvotes: 2
Reputation: 136144
If you want to do this in directive way only. Here is answer
angular.module('myApp.directives', []).
directive('exampleDirective', ['version', function(version) {
return {
link:function(scope,elm,attr) {
elm.on('click',function() {
//access exampleDirective2 behaviour
scope.exampleDirective2Function();
});
scope.exampleDirectiveFunction = function (){
//write your code here
}
}
}
}]).
directive('exampleDirective2', ['version', function(version) {
return {
link:function(scope,elm,attr) {
elm.on('change',function() {
//access exampleDirective behaviour
scope.exampleDirectiveFunction();
});
scope.exampleDirective2Function= function (){
//write your code here
}
}
}
}]);
Another way is, you can write a service, write a function in that, and use that service functions by injecting service into the directive.
Upvotes: 0
Reputation: 7078
One way to do this is to have a wrapper directive with a controller, which can then be shared between the directives if you use require
. A simpler, and perhaps better solution (as it doesn't depend on the DOM) is to have a common service that enables communication between the directives.
Upvotes: 1