Communicating between sibling components using services

Loading

When working with AngularJS 1.5+ components, one common challenge is how to enable communication between sibling components. Since sibling components do not have a direct parent-child relationship, services act as a shared data source or event mediator between them.


1. Why Use a Service for Sibling Communication?

Sibling components cannot communicate directly. They need a common service to:

  • Share data between components.
  • Emit and listen to events.
  • Ensure synchronization of shared state.

Diagram: How Services Facilitate Communication

 Parent Component
├─── Sibling Component A (Publishes Data/Event)
├─── Shared Service (Acts as Mediator)
├─── Sibling Component B (Subscribes to Data/Event)

By injecting the same service in both components, they can share data and communicate effectively.


2. Steps to Implement Communication via a Service

Step 1: Create a Shared Service

Step 2: Publish Data/Event from One Sibling

Step 3: Subscribe to the Data/Event in the Other Sibling


3. Implementing the Service for Communication

Create an AngularJS service (MessageService) that:

  • Stores shared data (message).
  • Provides methods to set and get the message.
  • Uses $rootScope.$broadcast() and $scope.$on() for event-based communication.

Step 1: Define the Service

app.factory('MessageService', function($rootScope) {
let sharedMessage = '';

return {
setMessage: function(msg) {
sharedMessage = msg;
$rootScope.$broadcast('messageUpdated', sharedMessage); // Notify listeners
},
getMessage: function() {
return sharedMessage;
}
};
});

The service stores and broadcasts the message.


4. Sibling Communication Using the Service

Step 2: First Sibling Component (Sender)

The first component sends a message using MessageService.setMessage().

app.component('siblingA', {
template: `
<div>
<h3>Sibling A</h3>
<input type="text" ng-model="$ctrl.newMessage">
<button ng-click="$ctrl.sendMessage()">Send Message</button>
</div>
`,
controller: function(MessageService) {
this.sendMessage = function() {
MessageService.setMessage(this.newMessage); // Set shared message
};
}
});

User types a message and clicks “Send Message”.
MessageService.setMessage() updates the shared data and broadcasts an event.


Step 3: Second Sibling Component (Receiver)

The second component listens for the messageUpdated event and updates its message.

app.component('siblingB', {
template: `
<div>
<h3>Sibling B</h3>
<p>Received Message: {{$ctrl.receivedMessage}}</p>
</div>
`,
controller: function($scope, MessageService) {
let ctrl = this;
ctrl.receivedMessage = MessageService.getMessage(); // Initialize message

$scope.$on('messageUpdated', function(event, data) {
ctrl.receivedMessage = data; // Update when message changes
});
}
});

Listens to the messageUpdated event.
Updates receivedMessage whenever MessageService broadcasts a new message.


5. Parent Component (Optional)

If the siblings are inside a parent component:

app.component('parentComponent', {
template: `
<div>
<sibling-a></sibling-a>
<sibling-b></sibling-b>
</div>
`
});

This ensures that both siblings are in the same scope but communicate via MessageService.


6. Alternative: Using Observables in Service

If you don’t want to use $rootScope.$broadcast(), you can use an observable approach.

Updated Service with Observables

app.factory('MessageService', function($rootScope) {
let message = '';
let listeners = [];

return {
setMessage: function(msg) {
message = msg;
listeners.forEach(cb => cb(msg));
},
getMessage: function() {
return message;
},
subscribe: function(callback) {
listeners.push(callback);
}
};
});

Updated Receiver Component Using Subscription

app.component('siblingB', {
template: `<p>Received: {{$ctrl.receivedMessage}}</p>`,
controller: function(MessageService) {
let ctrl = this;
ctrl.receivedMessage = MessageService.getMessage();

MessageService.subscribe(function(newMessage) {
ctrl.receivedMessage = newMessage;
});
}
});

No need for $rootScope.$broadcast()
More efficient and modular


7. Summary of Methods for Sibling Communication

MethodProsCons
$rootScope.$broadcastSimple, built-inCan cause performance issues if overused
Observable Pattern (Custom)Efficient, avoids $rootScopeRequires extra implementation
Parent as Mediator (Bindings)Angular-native, no extra serviceRequires modifying parent

8. When to Use a Service for Communication

When sibling components need to share data
When sibling components need event-based communication
When maintaining separation of concerns (no direct parent-child binding)

Avoid using services for small-scale communication when simpler methods (like using $parent or passing bindings) suffice.

Leave a Reply

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