Angular provides two methods for dispatching events Scope#$broadcast
which dispatches an event downwards to all child scopes, and Scope#$emit
which dispatches an event upward through the scope hierarchy. Both will call all registered listeners along the way and start from the scope the method was called from.
In cases where neither $emit
nor $broadcast
is suitable, Emit-To provides additional, more targetted path options.
If you use bower, simply bower install angular-emit-to
, otherwise download the angular-emit-to.js
source and include it in your code
<script src="angular.js"></script>
<script src="angular-emit-to.js"></script>
Add the rpd.emit-to
module dependency to your application.
angular.module('app', ['rpd.emit-to']);
Registers the scope of a given element with a custom identifier to enable event scope targetting and event scope transit with Scope#$emitTo and Scope#$emitSpanVia.
<div ng-controller="ctrl1" emit-to-id="ex1"></div>
<!-- Can also be interpolated -->
<div ng-repeat="i in [1,2,3,4,5]"
ng-controller="ctrl1"
emit-to-id="{{ 'ex' + i }}">
</div>
Dispatches an event to the specified scope by id or a list of ids as registered by the emit-to-id
directive.
scope.$emitTo(emit-to-id(s), eventname, [...args])
// As with Scope#$emit and Scope#$broadcast, an event object is returned
Register an element's scope with the emit-to-id
directive
<!-- emit-to-id must be attached to the same scope as the listener
as there is no event propagation -->
<div ng-controller="ctrl1" emit-to-id="ex1"></div>
<div ng-controller="ctrl1" emit-to-id="ex2"></div>
// Inside of the controller(s) that you've attached the emit-to-id, subscribe to an event as usual
app.controller('ctrl1', ['$scope', function($scope) {
$scope.$on("sample", function(e, text) {
// Do something
});
}]);
// Emit an event to the specified scope
$scope.$emitTo("ex1", "sample", "Event fired.");
// With a list of target ids
$scope.$emitTo(["ex1", "ex2"], "sample", "Event fired.");
--
Dispatches an event laterally (left and right) to all direct sibling scopes.
scope.$emitSpan(eventname, [...args])
// As with Scope#$emit and Scope#$broadcast, an event object is returned
<div ng-controller="siblingCtrl"></div>
<div ng-controller="siblingCtrl"></div>
<div ng-controller="siblingCtrl"></div>
// Inside of your controller(s), subscribe to an event as usual
app.controller('siblingCtrl', ['$scope', function($scope) {
$scope.$on("sample", function(e, text) {
// Do something
});
}]);
// Emit an event to all direct sibling scopes
// Note: there is no event propagation, you have Scope#$emit and Scope#$broadcast for that.
$scope.$emitSpan("sample");
--
Dispatches an event to all (nth-level) cousin scopes via their direct common ancestor (i.e. a grandparent or great-grandparent) as defined by the emit-to-id
directive.
Cousin scopes are scopes that descend from a common ancestor (n-levels above) and are inaccessible via the Scope#$$prevSibling and Scope#$$nextSibling properties due to inherent scope boundaries.
The most common example would be descendents of an ng-repeat
as every iteration creates a new scope. While there is a clear boundary dividing these children, there is also an implied relationship between them.
scope.$emitSpanVia(emit-to-id, eventname, [...args])
// As with Scope#$emit and Scope#$broadcast, an event object is returned
<div ng-repeat="i in [1,2,3,4]" emit-to-id="gp1">
<div ng-controller="cousinCtrl"></div>
</div>
<!-- Without ng-repeat -->
<div ng-controller="grandparentCtrl" emit-to-id="gp1">
<div ng-controller="parentCtrl">
<div ng-controller="cousinCtrl"></div>
</div>
<div ng-controller="parentCtrl">
<div ng-controller="cousinCtrl"></div>
</div>
</div>
// Inside of your controller(s), subscribe to an event as usual
app.controller('cousinCtrl', ['$scope', function($scope) {
$scope.$on("sample", function(e, text) {
// Do something
});
}]);
// Emit an event "sample" to all cousin scopes via
// the common ancestor (in this case grandparent) "gp1"
$scope.$emitSpanVia("gp1", "sample");
Try out the examples here
- More controlled order of event calls in emitSpanVia
- Unit tests
angular-emit-to
is MIT licensed