Angular Cats! Part 3 - Communicating with $broadcast

Continued from: Angular Cats! Part 2
Full Source Code: GitHub: jsCats/ngCatsHOM

In part 2 of this post, the source code in the event handlers within each controller was removed. That's because there's some interesting stuff going on that wouldn't have made sense without first knowing about one last module within the application: eventBroadcast.

To communicate clicks and cats between controllers, I found a dead simple solution that cobbles together an event dispatcher-esque system. When 'eventBroadcast' is injected into a controller, it will have access to its member variables - in this case, an event name, and a message. The eventBroadcast object can also broadcast events from the $rootScope, which will then trickle down the scope hierarchy and can be listened for by each controllers $scope. So it goes something like this:

  1. User clicks a cat thumbnail
  2. $scope.getDetail is called.
  3. The clicked cat object is attached to eventBroadcast.message.
  4. An event is broadcast from $rootScope with the name 'catClicked'
  5. CatDetailController's $scope responds to 'catClicked'
  6. eventBroadcast.message is checked for data.

Here is the ngClick handler in CatListController:


function CatListController($scope,$rootScope,$routeParams,CatsService,$location,eventBroadcast) {

$scope.getDetail = function() { // When a thumbnail is clicked, a 'catClicked' event is broadcast, // and the data for the clicked cat is attached to eventBroadcaster eventBroadcast.broadcast('catClicked',{cat:this.cat}); };

... }

Here is the actual eventBroadcast module:


.factory('eventBroadcast', function($rootScope) { // eventBroadcaster is the object created by the factory method. var eventBroadcaster = {};

// The message is a string or object to carry data with the event.
eventBroadcaster.message = '';

// The event name is a string used to define event types.
eventBroadcaster.eventName = '';

// This method is called from within a controller to define an event and attach data to the eventBroadcaster object.
eventBroadcaster.broadcast = function(evName, msg) {
    this.message = msg;
    this.eventName = evName;
    this.broadcastItem();
};

// This method broadcasts an event with the specified name.
eventBroadcaster.broadcastItem = function() {
    $rootScope.$broadcast(this.eventName);
};

return eventBroadcaster; })

And the handler for 'catClicked' in CatDetailController:


function CatDetailController($scope,$rootScope,eventBroadcast) {

// When 'catClicked' is broadcast, we know that new cat data needs to be loaded from eventBroadcast $scope.$on('catClicked',function() { showCat(eventBroadcast.message.cat); });

...

var showCat = function(cat) { $scope.cat = cat; $scope.catIndex = $rootScope.catCollection.indexOf(cat); }

}

And there you have it! A rudamentary technique for communicating between controllers. However, after reading this Google Groups thread, I learned that there are some flaws with this method. Thomas Burleson created a more robust pub/sub module that acts as a message queue, which is more scalable, flexible, and doesn't rely so much on $rootScope. A demo of the Messaging Service module is on jsFiddle, and the code can be download from his site. I hope to try this out very soon.

comments powered by Disqus