Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:

  • Good for one-time events

Disadvantages:

  • Does not work between siblings, unless a common ancestor, like $rootScope, is used

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:

  • Good for top-to-bottom data propagation

Disadvantages:

  • Not-as-good for bottom-to-top, since it requires an object (as opposed to a primitive)
  • Calling ancestor functions creates a tight coupling
  • Does not work between siblings, unless a common ancestor, like $rootScope, is used

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:

  • Good for child scope not created by controllers, e.g. like within ng-repeat

Disadvantages:

  • Doesn't work at all for one-time events
  • Not very readable code

Other notable mentions:

  • Shared Service with specialized functionality
  • More general Pub/Sub Service
  • $rootScope
like image 652
New Dev Avatar asked Nov 05 '14 07:11

New Dev


2 Answers

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.

like image 149
aUXcoder Avatar answered Oct 10 '22 15:10

aUXcoder


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.

like image 45
Samuel Neff Avatar answered Oct 10 '22 16:10

Samuel Neff