Share Data Between Parent and Child Components Using RxJS Subject

In Angular applications, parent and child components often need to communicate effectively. While traditional approaches use @Input()
and @Output()
, a more flexible way to achieve bidirectional data sharing is by using an RxJS Subject
.
A Subject
allows both components to send and receive data, making it a powerful tool for managing shared state dynamically. Let’s dive into implementing this step by step.
Step 1: Creating the Shared Service
The first step is to create an Angular service that will act as the bridge between the parent and child components. This service will contain an RxJS Subject
, which both components can use to send and receive data.
Service Code
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class DataService {
private dataSubject = new Subject<string>(); // Creating a Subject
data$ = this.dataSubject.asObservable(); // Exposing the Subject as an Observable
// Method to send data
sendData(data: string) {
this.dataSubject.next(data);
}
}
How It Works
- The service contains an
RxJS Subject
, which acts as both an observable (to listen for updates) and an observer (to emit data). - The
sendData()
method updates the Subject whenever a component calls it. - Any component subscribing to
data$
will automatically receive new data when it is emitted. - Since
Subject
allows multiple subscribers, both the parent and child components can listen for changes dynamically.
This service enables smooth, reactive communication between the parent and child components, eliminating the need for direct data binding or event emitters.
Step 2: Implementing the Parent Component
Now that we have the shared service in place, we integrate it into the parent component. The parent component will:
- Send data to the child through the service.
- Listen for updates from the child using the
RxJS Subject
.
Parent Component Code
import { Component } from '@angular/core';
import { DataService } from '../data.service';
@Component({
selector: 'app-parent',
template: `
<h2>Parent Component</h2>
<input [(ngModel)]="parentData" placeholder="Enter data to send" />
<button (click)="sendData()">Send to Child</button>
<p>Data from Child: {{ childData }}</p>
<app-child></app-child>
`,
})
export class ParentComponent {
parentData: string = '';
childData: string = '';
constructor(private dataService: DataService) {
// Receiving data from the child
this.dataService.data$.subscribe((data) => {
this.childData = data;
});
}
sendData() {
// Sending data to the child
this.dataService.sendData(this.parentData);
}
}
How It Works
- Sending Data: When the parent calls
sendData()
, it updates theRxJS Subject
in the shared service. - Receiving Data: The parent subscribes to
data$
, allowing it to listen for updates from the child. - Dynamic Interaction: Whenever the child sends new data, it automatically updates in the parent.
- Decoupled Communication: Since both components rely on the shared service, they don’t need direct references to each other.
- Reactive Updates: Changes occur instantly across components, enhancing real-time interaction.
This setup ensures that the parent component can efficiently send and receive data without relying on traditional Angular bindings like @Input()
and @Output()
, making communication much more flexible.
Step 3: Implementing the Child Component
Now that the parent component is set up, the child component needs to send updates back to the parent. It does this by using the same shared service.
Child Component Code
import { Component } from '@angular/core';
import { DataService } from '../data.service';
@Component({
selector: 'app-child',
template: `
<h3>Child Component</h3>
<input [(ngModel)]="childData" placeholder="Enter data to send" />
<button (click)="sendData()">Send to Parent</button>
`,
})
export class ChildComponent {
childData: string = '';
constructor(private dataService: DataService) {}
sendData() {
// Sending data to the parent
this.dataService.sendData(this.childData);
}
}
How It Works
- Sending Data: The child component calls
sendData()
, which updates theRxJS Subject
in the shared service. - Parent Receives Data: Since the parent component subscribes to
data$
, it automatically receives updates whenever the child sends new data. - No Direct Interaction: The child does not need to reference the parent directly; instead, it communicates via the shared service.
- Decoupled & Scalable: This approach allows multiple components to send and receive data effortlessly.
- Instant Updates: Because RxJS manages the data flow reactively, changes are processed in real-time.
This setup ensures smooth bidirectional communication, allowing the child to send updates dynamically while keeping the application structure flexible and efficient.
Final Thoughts
By using RxJS Subject
, we’ve established a seamless bidirectional communication between a parent and child component without relying on traditional Angular bindings like @Input()
and @Output()
.
This method allows components to send and receive data reactively, making it especially useful in scenarios where multiple components need to share state efficiently.
Why Use This Approach?
- Decoupling Components: The parent and child do not need direct references to one another.
- Centralized State Management: The shared service controls the data flow, improving maintainability.
- Reactive Updates: Components automatically receive new data, creating a smooth real-time experience.
- Scalability: This pattern can be extended for more complex communication between multiple components.
- Better Flexibility: Unlike traditional methods, this approach works well across nested components and dynamic interactions.
Subscribe to my newsletter
Read articles from sourcetrooper directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
