Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / AngularJs

Angular Controller Communication using Delegates

0.00/5 (No votes)
3 May 2015CPOL2 min read 10.6K  
Angular Controller communication using delegates

I recently found the need for two controllers to communicate a lot more than normal events would easily enable. I needed one controller to ask another for information, without them being too strongly coupled (because nobody likes that). There are several ways of solving this problem, but I found that using a delegate pattern was the most elegant solution for my problem.

So the way this works is that a delegate object is sent to the controller that needs to be ‘asking the questions’, so that it knew where to get answers. The delegate object comes from another controller that can help answer those questions.

Simple diagram showing how controller communication using delegates work

Simple diagram showing how controller communication using delegates work

The way this works is fundamentally very simple. The Sub Controller needs someone to answer questions or do something that it cannot do by itself. The reason it cannot do it, is probably because it shouldn’t be concerned with how to get the answers. Its job is to get a hold of the answer and display it (or use it for something at least). Someone else knows how to answer the question. So it needs a delegate to do the job for it.

The Main Controller creates an object that is designed to work for the Sub Controller. How it gets the answer is not important. It can use a service to search for it elsewhere. It doesn’t matter. The point is that when the Sub Controller asks the question, the delegate is the one who will ultimately answer the question for the Sub Controller.

For this to work, the Main Controller needs to send the delegate object to the Sub Controller. This is done using a directive isolate scope and bind a parent scope property to the isolate scope:

PHP
.directive('myDirective', function () {
  return {
    scope: {
      delegate: '='
    },
    ...
  }
XML
<my-directive delegate="someObjectThatCanWorkAsDelegate"></my-directive>

The ‘=’ allows the controller for myDirective to access the delegate on its isolate scope. Very handy!

The rest is just a matter of wiring things up and calling the correct stuff. I will show a simple example, that I have also implemented in a plunker: http://plnkr.co/edit/xNxScz8yy7SWQNk0r6RA?p=preview

Main Controller

PHP
.controller('MainController', function ($scope) {
  var vm = this;
  vm.delegateObject = {
    getSeriousAnwser: function () {
      return "INSERT SERIOUS ANSWER HERE";
    },
    getJokeAnswer: function () {
      return "INSERT FUNNY JOKE HERE";
    }
  };
})

Directive with Sub Controller

PHP
.directive('myDirective', function () {
  return {
    restrict: 'E',
    scope: {
      delegate: '='
    },
    controller: function ($scope) {
      var vm = this;
      vm.answer = 'no answer yet...';
      vm.getAnswer = function () {
        if (vm.joke) {
          vm.answer = $scope.delegate.getJokeAnswer();
        } else {
          vm.answer = $scope.delegate.getSeriousAnwser();
        }              
      }
    },
    controllerAs: 'vm',
    template: 'Joke <input type="checkbox" ng-model="vm.joke" >' +
              '<br><button ng-click="vm.getAnswer()">Get Answer</button>' +
              '<br>{{vm.answer}}'
  };
});

HTML

XML
<body ng-controller="MainController as vm">
  <my-directive delegate="vm.delegateObject"></my-directive>
</body>

I know there is not only one way to solve this sort of problem. You can in theory use events back and forth, but that will soon get very ugly and strongly coupled.

The other way, which seems to be popular, is to use a service like a messaging bus. I didn’t think it would be a good fit for the situation I was in, but it would certainly be better if you were not able to control the scopes and use directives in the same way as I do here. It all depends on the situation. It’s just an alternative for controller communication.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)