2

I have a directive that powers an HTML5 Canvas visualization. This directive has a wide array of methods to modify different parts of the visualization. The issue is that multiple controllers that have a different parent/child/sibling relationship need to communicate to this directive. Right now I have it wired this pretty awful way of emitting events up to the parent controller of the directive and then broadcasting them to the directive.

I have heard of using a service to do something like this, but nothing really explain why. I thought of using something like this:

angular.service('CanvasCommunication', function($rootScope) { 
   this.canvasAction = function() { $rootScope.broadcast('canvasAction'); };
}

And then have listener in the canvas to actual execute that action. This service could be then injected into any controller that communicates with the canvas.

The issue with this is that $rootScope.broadcast() has terrible performance and I want to make sure this communication channel is built in the most efficient way.

Has anybody dealt with something like this and thought of something better?

Alexander Ventura
  • 1,150
  • 1
  • 10
  • 32
  • Not sure that I fully understand what you're trying to do. Normally if I have a directive that will be shared & interact with multiple controllers, I will create a service that has a property, and inject the service into all of the necessary Controllers & Directives. I can then use $watch to make necessary updates, and alter the property from wherever I want. Not sure this is the best approach but it works. – Kurt Funai Mar 25 '14 at 20:36

1 Answers1

2

I've had the same issue - controllers needing to interact with each other, different parts of the app sending messages to each other, etc. In my projects, I've implemented a MessageService. Here's a very basic version of one (but honestly more than sufficient):

module.factory('MessageService',
  function() {
    var MessageService = {};

    var listeners = {};
    var count = 0;
    MessageService.registerListener = function(listener) {
      listeners[count] = listener;
      count++;

      return (function(currentCount) {
        return function() {
          delete listeners[currentCount];
        }
      })(count);
    }

    MessageService.broadcastMessage = function(message) {
      var keys = Object.keys(listeners);

      for (var i = 0; i < keys.length; i++) {
        listeners[keys[i]](message);
      }
    }

    return MessageService;
  }
);

You might want to have listeners registered for particular subjects, and filter messages by subject, or not. Mine also queue messages on subjects until they're cleared, so that the messages can be viewed when a new view loads (in order to pair for ex. 'Success - Saved file' with a page change).

Robert Balicki
  • 1,583
  • 2
  • 16
  • 24