var app = angular.module('app', []);

app.directive('someDirective', ['$log', 'someService', function($log, someService){
  return {
    restrict: 'A',
    controllerAs: 'someDirective',
    controller: function($scope, $element){
      
      // a local method bound to "this"
      var doSomething = (function doSomething(someData){
        $log.log('Using the ctrl: ' + this.someVar);
        $log.log('Does something with ' + someData);
      }).bind(this);
      
      // a local method not bound to "this"
      function doAnotherThing(someData){
        $log.log('Using the ctrl: ' + vm.someVar);
        $log.log('Does another thing with ' + someData);
      }
      
      // a local method bound to "this"
      var thingOne = (function thingOne(withData){
        $log.log('Using the ctrl: ' + this.someVar);
        $log.log('Thing One with data: ' + withData);
      }).bind(this);
      
      // a local method not bound to "this"
      function thingTwo(withData){
        $log.log('Using the ctrl: ' + vm.someVar);
        $log.log('Thing Two with data: ' + withData);
      }
      
      // a local method not bound to "this"
      function thingThree(withData){
        $log.log('Using the ctrl: ' + vm.someVar);
        $log.log('Thing Three with data: ' + withData);
      }
      var vm = this;
      vm.someVar = 5;
      // set async events
      //can be 3 diff methods: success, error and notify
      // for this demo we use the same method
      var unsetDoSomething = someService.setAsyncListener('doSomething', doSomething, doSomething, doSomething);
      var unsetDoAnotherThing = someService.setAsyncListener('doSomething', doAnotherThing, doAnotherThing, doAnotherThing);
      
      // set sync events
      someService.setSyncListener('lotsOfThings', thingOne);
      someService.setSyncListener('lotsOfThings', thingTwo);
      someService.setSyncListener('lotsOfThings', thingThree);
      
      // clear sync events from the service to prevent memory leak
      $element.on('$destroy', function(){
        // unset sync events
        someService.unsetSyncListener('lotsOfThings', thingOne);
        someService.unsetSyncListener('lotsOfThings', thingTwo);
        someService.unsetSyncListener('lotsOfThings', thingThree);
        
        unsetDoSomething();
        unsetDoAnotherThing();
      });
    }
  }
}]);

app.service('someService', ['$q', '$log', function($q, $log){
  function unsetAsyncListener(){
      if (!this.promisesArray){
        return;
      }
      
      var promisesArray = this.promises;
      var unsetIndex = promisesArray.indexOf(this.pending);
      promisesArray.splice(unsetIndex, 1);
      this.pending = null;
      this.promisesArray = null;
  }
  
  var asyncListeners = {}; //holds the listeners
  var syncListeners = {};
  
  var myService = {
    setAsyncListener: function setAsyncListener(name, resolve, reject, notify){
      if (!angular.isDefined(asyncListeners[name])){
        asyncListeners[name] = $q.defer();
      }
      
      asyncListeners[name].promise.then(resolve, reject, notify);
      
      return unsetAsyncListener.bind({
        promisesArray: asyncListeners[name].promise.$$state.pending, 
        pending: asyncListeners[name].promise.$$state.pending[asyncListeners[name].promise.$$state.pending.length-1]
      });
    },
    setSyncListener: function setSyncListener(name, callback){
      if (angular.isUndefined(syncListeners[name])){
        syncListeners[name] = [];
      }
      syncListeners[name].push(callback);
    },
    unsetSyncListener: function unsetSyncListener(name, callback){
      if (angular.isUndefined(syncListeners[name])){
        return;
      }
      // get the index and splice the listener
      var index = syncListeners[name].indexOf(callback);
      syncListeners[name].splice(index, 1);
    },
    method1: function needsToDoSomethingWithSomeData(someData){
      // runs "doSomething" in the directive
      asyncListeners.doSomething.notify(someData);
    },
    aVeryCoolAction: function needsToDoLotsOfThings(withData){
      for (var i = 0; i < syncListeners.lotsOfThings.length; i++){
        syncListeners.lotsOfThings[i](withData);
      }
    }
  }
  
  return myService;
}]);

app.controller('MainCtrl', ['$scope', 'someService', function ($scope, someService) {
  
  var vm = this;
  
  vm.doSomething = function(){
     someService.method1(Math.random());
     someService.aVeryCoolAction(Math.random());
  }
}]);
.grid {
  width: 600px;
}

.hovered{
  outline: red 2px solid;
}
<!doctype html>
<html ng-app="app">
  <head>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.js"></script>
    <link rel="stylesheet" href="main.css" type="text/css">
  </head>
  <body>

<div ng-controller="MainCtrl as ctrl">
  <button ng-click="hide = !hide">Hide</button>
  <button ng-if="!hide" some-directive ng-click="ctrl.doSomething()">Do Something</button>
</div>


    <script src="app.js"></script>
  </body>
</html>