![]()
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
| Method | Pros | Cons |
|---|---|---|
| $rootScope.$broadcast | Simple, built-in | Can cause performance issues if overused |
| Observable Pattern (Custom) | Efficient, avoids $rootScope | Requires extra implementation |
| Parent as Mediator (Bindings) | Angular-native, no extra service | Requires 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.
