Share Data Between Parent and Child Components Using RxJS Subject

sourcetroopersourcetrooper
4 min read

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

  1. Sending Data: When the parent calls sendData(), it updates the RxJS Subject in the shared service.
  2. Receiving Data: The parent subscribes to data$, allowing it to listen for updates from the child.
  3. Dynamic Interaction: Whenever the child sends new data, it automatically updates in the parent.
  4. Decoupled Communication: Since both components rely on the shared service, they don’t need direct references to each other.
  5. 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

  1. Sending Data: The child component calls sendData(), which updates the RxJS Subject in the shared service.
  2. Parent Receives Data: Since the parent component subscribes to data$, it automatically receives updates whenever the child sends new data.
  3. No Direct Interaction: The child does not need to reference the parent directly; instead, it communicates via the shared service.
  4. Decoupled & Scalable: This approach allows multiple components to send and receive data effortlessly.
  5. 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.
0
Subscribe to my newsletter

Read articles from sourcetrooper directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

sourcetrooper
sourcetrooper