Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

$rootScope as event aggregator

I am using angular-js. I have a service that need to trigger event each time something occurs. For doing it I need an object that will act as event aggregator.

  1. Do I need to build one? Or should I use the $rootScope?
  2. In case I should use $rootScope, how can I ensure that there is no event names conflicts?
  3. Is it efficient to use $rootScope for events that don't need them to propagate to child scopes?
like image 554
Naor Avatar asked Jul 13 '13 03:07

Naor


2 Answers

I modeled and implemented the following mechanism in a web project for tablets:

  1. Define notifications in your services. I did not want to use the term events since I did not want it to be confused with DOM events by other developers in my team. And a semi-typed name for a notification is easier for IDE with intellisense support and for debugging. For example, I have one Device service that would $broadcast(Device.Notification.OrientationDidChange) when a tablet device's orientation is changed.

  2. Use Scope objects to $broadcast or $emit notifications, depending on your need. For example,

    • For global notifications like the previous one, I do: $rootScope.$broadcast(Device.Notification.OrientationDidChange). So all listeners can listen on their own scope without injecting $rootScope.
    • For local notifications that could possibly only affect the current scope (and its children), such as a notification that a scope needs to tell all its child scopes that the layout of the current controller is changed, usually I do: scope.$broadcast(UI.Notification.NeedsLayout), where UI is a predefined service to hold UI related constants, and scope is the current scope.
    • For certain notifications that a child scope needs to send upwards, for example, a slider directive that tells ascendant scopes that the rangeStart value has changed (in addition to regular two way binding), I use: scope.$emit(Slider.Notification.RangeStartDidChange), where scope is the current scope.
  3. This approach is a bit verbose in a small project. You might want to stick to using $rootScope.$emit(Notification) all the time, and let all listeners to do $rootScope.$on(Notification, callback) to receive these notifications.

  4. In some situations, you might want to define these notifications in a centralized service in order to more easily avoid name conflicts. It really based upon your project's naming convention.

  5. The implementation (actual values) of these notifications may vary. I prefer using strings.

  6. With $broadcast or $emit you can also actually pass additional arguments to the listeners, for example, $broadcast(Notification, arg1, arg2)... Angular's documentation is quite detailed.

like image 149
yuxhuang Avatar answered Sep 18 '22 17:09

yuxhuang


Take a look at http://docs.angularjs.org/api/ng.$rootScope.Scope#$broadcast.

  1. Using $rootScope as event aggregator is perfectly fine unless you are triggering events outslide digest cycle or triggering multiple (100+) events at the same time where some other solutions may be more appropriate .
  2. One accepted practice would be to use namespacing (namespace:event - pattern used by Backbone.Marionette)
  3. Use $emit on a child scope instead of $broadcast on $rootScope - $emit propagates only upwards, where $broadcast propagates downwards - to all children
like image 20
g00fy Avatar answered Sep 22 '22 17:09

g00fy