The neat stuff you can do with AngularJS continues to blow my mind! No matter how complex I think the problem I’m having is, Angular seems to always have an elegantly simple solution. And on those rare occasions when the functionality I’m looking for is not built into Angular’s core, there is usually a solution out there in the Angular community. I think what I love most about Angular is that it is so forward-thinking, and that progressiveness seems to have rubbed off on the community. However, this is not about my infatuation with Angular. This article stems from a problem I tackled recently.

Why AngularJS?

I was developing an application that, due to its architecture, had multiple controllers on the page at the same time. The exact content and number of controllers displayed on the page were dependent upon the viewer’s permissions; i.e. what one user sees might be different from what another user sees. For example, here are two possible user views of the same application page using a (rough) wireframe layout:

My Application: User 1 View
The User 1 View Wireframe
My Application: User 2 View
The User 2 View Wireframe

In certain scenarios, when a user performs an action inside the Directive1_Ctrl, something would need to occur inside Controller 3; and then based on the logic inside Controller 3, something else would need to occur inside Controller 2 or Controller 4, whichever one was currently present on the page.
If we knew that Directive1_Ctrl would always be the child of Controller 3 we could simply use Angular’s built-in $parent ability to execute the required $scope function inside Controller 3. However, as you can see, there is a possible configuration where Directive1_Ctrl will be nested inside Directive2_Ctrl.

In addition, Angular only allows controllers one-way access. By that I mean a child can access its parent using $parent, but the parent does not have access in the same manner to its child. This makes sense because a controller may have at most one parent, but may contain many children. So in the future, if we needed to pass information back down into the Directive1_Ctrl and Directive2_Ctrl controllers we would be out of luck.
This is where Angular’s $emit, $broadcast and $on event functions come into play.

$emit(name, args);
Just like its name implies, $emit acts like a beacon sending out information to anyone willing to listen. When $emit is called, it sends out an event name upwards through the scope hierarchy notifying all registered $rootScope.Scope listeners. Any listener prepared for that named event will execute its associated function. The listener also has access to any of the [optional] arguments passed via $emit. As the event progresses up the scope hierarchy, each listener has the ability to silence the event, stopping it from continuing on its path.
In our example application (above), we would use $emit to enable Directive1_Ctrl to communicate with Controller 3. This will allow our two controllers to communicate without having to know if Directive1_Ctrl is a direct child of Controller 3, or a grandchild or great-grandchild.

$broadcast(name, args);
The $broadcast function is the inverse of $emit. I like to think of $broadcast as a school principal giving the daily announcements over the PA system to all of their staff and students. When $broadcast is called, it sends out an event name downwards through the scope hierarchy notifying all registered $rootScope.Scope listeners. Any listener prepared for that name event will execute its associated function. Just like $emit, each listener has access to the [optional] arguments and it can silence the event, stopping it from continuing on.
In our example application, we would use $broadcast to enable Controller 3 to communicate with Directive1_Ctrl without having to worry about what level child Directive1_Ctrl is in comparison to Controller 3. Similar to $emit, the $broadcast event doesn’t actually require another controller to listen for it. If a controller sends out an $emit or $broadcast event and nobody is listening for that name, that’s okay.

$on(name, listener);
The $on function pulls it all together. Within a controller, $on listens for events having a certain name. When a matching event is received, it executes the listener function. The listener function is required to have at least one parameter, and that is an event object. After the event object, all expected parameters are added.
For example, our Directive1_Ctrl is going to $emit('trackOder', orderTime) where the event name is trackOder and it is passing on an argument, orderTime, which is just a variable declared somewhere inside Directive1_Ctrl’s scope. In order for Controller 3 to receive this event and utilize the orderTime argument, it would need to be constructed with the following:
$on('trackOder', function(event, orderTime){ … });
But be careful! Listeners are global. If Directive2_Ctrl also sends out an event called 'trackOder', or perhaps the $rootScope sends out a 'trackOder' event, Controller 3 may pick up and execute that listener, even if we didn't intend the $emit or $broadcast to trigger Controller 3’s event listener. To avoid this, the event comes with a property called targetScope which defines the event originator. There are additional properties on the event object and I would highly recommend reviewing them before you start building your listeners.

Finally, what if there were occasions when Controller 3 would need to communicate with Controller 2 and/or Controller 4? You might notice from my wireframes that Controller 3 is at the same hierarchy level as Controller 2 and Controller 4, and so far we've discussed only ways to send messages up or down the scope hierarchy.
To solve this, we’ll need to inject the $rootScope into our sending controller. Because the $rootScope is the “principal” of our application, so to speak, it is able to send a $broadcast event on behalf of this controller to every single scope on our page; and I do mean every single scope. If your listeners are not configured correctly, you may end up with a lot more events triggering that you had expected!

More Posts on AngularJS

Dynamic Directive TemplateUrls in AngularJS

Beginner’s Guide To AngularJS


Next Steps

Review our case studies and engagements where we helped companies just like yours solve a variety of business needs.


About Oakwood

Since 1981, Oakwood has been helping companies of all sizes, across all industries, solve their business problems.  We bring world-class consultants to architect, design and deploy technology solutions to move your company forward.   Our proven approach guarantees better business outcomes.  With flexible engagement options, your project is delivered on-time and on budget.  11,000 satisfied clients can’t be wrong.

Like what you've read? Please spread the word!

Leave a Reply

Your email address will not be published. Required fields are marked *