New Dev
New Dev

Reputation: 49590

Communication between controllers in Angular

I'm familiar with the following methods to implement communication between controllers.

Are there others? Are there better approaches / best practices?


$broadcast/$emit

.controller("Parent", function($scope){
  $scope.$broadcast("SomethingHappened", {..});
  $scope.$on("SomethingElseHappened", function(e, d){..});
})
.controller("Child", functions($scope){
  $scope.$broadcast("SomethingElseHappened", {..});
  $scope.$on("SomethingHappened", function(e, d){..});
})
.controller("AnotherChild", functions($scope){
  $scope.$on("SomethingHappened", function(e, d){..});
});

or, from the View:

<button ng-click="$broadcast('SomethingHappened', data)">Do Something</button>

Advantages:

Disadvantages:


Scope inheritance of functions

<div ng-controller="Parent">
  <div ng-controller="Child">
    <div ng-controller="ChildOfChild">
       <button ng-click="someParentFunctionInScope()">Do</button>
    </div>
  </div>
</div>

or, in code

.controller("ChildOfChild", function($scope){
   $scope.someParentFunctionInScope();
});

Advantages:

Disadvantages:


Scope inheritance + $watch

Controllers only react to change in scope-exposed data and never call functions.

.controller("Parent", function($scope){
  $scope.VM = {a: "a", b: "b"};
  $scope.$watch("VM.a", function(newVal, oldVal){
    // react
  });
}

Advantages:

Disadvantages:

Other notable mentions:

Upvotes: 9

Views: 2508

Answers (3)

Samuel Neff
Samuel Neff

Reputation: 74949

I use functionality-specific shared services to communicate between controllers.

You can create a generic shared service to have a central point to subscribe to and broadcast events, but I find functionality-specific services to be easier to maintain over time, especially as the project and team grows.

Upvotes: 5

rahpuser
rahpuser

Reputation: 1249

-- There is another option to inheritance and share data between your controllers:

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

    var parent = function($scope){
        $scope.parent = {
             parentData: 'some data'
        }
    };

    // you could do some prototyping as well
//parent.prototype.parent2 = {
//    parentData: 'some more data'
//};

    var child = function($scope){
        parent.call(this, $scope);
        //$scope.parent2 = this.parent2; here is how you access that data.
    };
    child.prototype = Object.create(parent.prototype);
    child.prototype.constructor = child;


app.controller('parent', parent);

app.controller('myController', child);

This approach give you an advantage:

  • Works with siblings scopes and DOM structure is not needed.

You could continue working with the objects creating custom properties, 'freezing' the data variables to persist the same data and ensure data is not modified, etc.

At the end, I prefer to use a service to share data between controllers and use the observer pattern or pub/sub with rootscope emit/on to acknowledge of actions within controllers.

Upvotes: 0

aUXcoder
aUXcoder

Reputation: 1077

As Samuel said, using a service to sharing data is a recommended method. The idea is that the state of the data are maintained consistently, regardless of any controller. This two articles can give you an idea of "how to" and "why": Sharing Data Between Controllers, The state of angularjs controllers.

Upvotes: 6

Related Questions