Implementing event-driven communication with $broadcast and $emit

Loading

In AngularJS, event-driven communication allows different components of an application to communicate with each other efficiently. AngularJS provides the $broadcast and $emit methods on $scope to send events, along with $on to listen for them.

This guide will explore:

  • The differences between $broadcast and $emit
  • How to use them effectively with examples
  • Best practices and when to use them

Step 1: Understanding $emit, $broadcast, and $on

1. $emit(eventName, data)

  • Sends an event upwards from the current $scope to its parent scopes, up to the $rootScope.
  • Only parent scopes and $rootScope can listen to this event.
  • Typically used when a child scope needs to notify a parent or global scope.

2. $broadcast(eventName, data)

  • Sends an event downwards from the current $scope to all its child scopes.
  • Only child scopes can listen to this event.
  • Typically used when a parent scope wants to notify its children.

3. $on(eventName, callback)

  • Used to listen for events ($emit or $broadcast) in any scope.

Step 2: Using $emit to Communicate Upwards

Imagine a scenario where a child controller needs to notify the parent controller when an action occurs.

Example – Using $emit to Notify the Parent Scope

HTML

<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="UTF-8">
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script>
<title>AngularJS $emit Example</title>
</head>
<body ng-controller="ParentCtrl">

<h2>Parent Received: {{ parentMessage }}</h2>

<div ng-controller="ChildCtrl">
<button ng-click="sendMessage()">Send Message to Parent</button>
</div>

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

JavaScript (app.js)

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

app.controller('ParentCtrl', function($scope) {
$scope.parentMessage = "No message received";

// Listen for the event emitted from the child scope
$scope.$on('childEvent', function(event, data) {
$scope.parentMessage = data; // Update the parent scope
});
});

app.controller('ChildCtrl', function($scope) {
$scope.sendMessage = function() {
$scope.$emit('childEvent', 'Message from Child!'); // Emit event upwards
};
});

How It Works

  • The Child Controller emits the event childEvent using $scope.$emit().
  • The Parent Controller listens for the event using $scope.$on().
  • When the button is clicked, the event triggers and updates the parent’s message.

Use $emit when a child needs to communicate with a parent or $rootScope.


Step 3: Using $broadcast to Communicate Downwards

Now, let’s see how a parent controller can notify its child controllers using $broadcast.

Example – Using $broadcast to Notify Child Scopes

HTML

<body ng-controller="ParentCtrl">
<button ng-click="sendBroadcast()">Send Broadcast to Children</button>

<div ng-controller="ChildCtrl">
<h2>Child Message: {{ childMessage }}</h2>
</div>
</body>

JavaScript (app.js)

app.controller('ParentCtrl', function($scope) {
$scope.sendBroadcast = function() {
$scope.$broadcast('parentEvent', 'Message from Parent!');
};
});

app.controller('ChildCtrl', function($scope) {
$scope.childMessage = "No message received";

$scope.$on('parentEvent', function(event, data) {
$scope.childMessage = data; // Update child scope with the message
});
});

How It Works

  • The Parent Controller sends an event parentEvent using $scope.$broadcast().
  • The Child Controller listens for parentEvent using $scope.$on().
  • When the button is clicked, the event triggers and updates the child’s message.

Use $broadcast when a parent needs to notify its children.


Step 4: Using $rootScope.$emit and $rootScope.$broadcast for Global Events

If you need an event to be available throughout the application, use $rootScope.

Example – Global Event Communication Using $rootScope.$emit

HTML

<body ng-controller="GlobalCtrl">
<button ng-click="notifyAll()">Notify All Controllers</button>

<div ng-controller="ChildCtrl">
<h2>Child Received: {{ childMessage }}</h2>
</div>
</body>

JavaScript (app.js)

app.run(function($rootScope) {
$rootScope.$on('globalEvent', function(event, data) {
console.log("Global Event Received: ", data);
});
});

app.controller('GlobalCtrl', function($scope, $rootScope) {
$scope.notifyAll = function() {
$rootScope.$emit('globalEvent', 'This is a global event!');
};
});

app.controller('ChildCtrl', function($scope, $rootScope) {
$scope.childMessage = "No global event yet";

$rootScope.$on('globalEvent', function(event, data) {
$scope.childMessage = data;
});
});

How It Works

  • $rootScope.$emit() triggers a global event.
  • Any controller listening on $rootScope can receive this event.

Use $rootScope.$emit for application-wide event communication.


Step 5: Best Practices for Event Handling

Best PracticeExplanation
Minimize Global Events$rootScope.$emit and $rootScope.$broadcast should be used sparingly to avoid complexity.
Unregister Event ListenersUse $scope.$on('$destroy', function() { ... }) to clean up event listeners when a scope is destroyed.
Use Services for Shared DataIf two controllers need to share data, using a service is often a better option.
Avoid Excessive $broadcast and $emitToo many events can make debugging difficult. Consider direct function calls or services instead.

Conclusion

MethodCommunication DirectionUse Case
$emitUpwards to parent scopeWhen a child needs to notify a parent
$broadcastDownwards to child scopesWhen a parent needs to notify its children
$rootScope.$emitGlobal event for all controllersWhen an event should be available app-wide
$onListening for eventsUsed to capture emitted or broadcasted events

Use $emit for child-to-parent communication.
Use $broadcast for parent-to-child communication.
Use $rootScope.$emit sparingly for global events.

Leave a Reply

Your email address will not be published. Required fields are marked *