How to communicate with components in Angular by using Subject and Observables?

If you are building an Angular application you have probably encountered this problem: communicate with other components. Dealing with components when there is a parent-child link between them is quite easy. You just have to use Input() and Output() to make them communicate. But what about this situation:

<app-a></app-a>
<app-b></app-b>

app.component.html

So, In this situation there is no parent-child relation and you would like to transfer data between the two components. Let’s see how to communicate with components by using subject and Observables. (In this quick tutorial, we assume that you know how observables works).

Create the message service

import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class MessageService {
  private subject = new Subject<any>();

  sendMessage(message: string) {
    this.subject.next({ msg: message });
  }

  getMessage(): Observable<any> {
    return this.subject.asObservable();
  }

  close() {
    this.subject.complete();
  }

}

message.service.ts

For a basic usage, you will find three functions. One for sending message, another for receiving it and the last one to close the pipe. The ‘sendMessage(msg: string)’ function will simply send the message to the pipe by using the next function. The ‘getMessage()’ simply turn the subject object into an observable and in that way we can subscribe to the pipe for receiving messages.

The communication between the components

After creating the message service, the next step is quite easy. Let’s assume that the A component sends a message to the other component. Here is the result:



  Hello, I'm the A component


<button (click)="sendMessage('Hello I\'m sending you a msg from the A component')">
  Send Message to the B component
</button>

a.component.html

import {Component, OnInit} from '@angular/core';
import {MessageService} from '../../services/message.service';

@Component({
  selector: 'app-a',
  templateUrl: './a.component.html',
})
export class AComponent implements OnInit {

  constructor(private messageService: MessageService) {};

  ngOnInit(): void {
  }

  sendMessage(value: string) {
    this.messageService.sendMessage(value);
  }

}

a.component.ts

Here we just send a message to the B component when we click on the button. All components which subscribed to the the message service will receive the message. (This means you can communicate with more than two components). To finish, here is how we receive the message in the B component:



  Hello, I'm the B component 
  {{ receiveMessage }}


b.component.html

import {Component, OnDestroy, OnInit} from '@angular/core';
import {MessageService} from '../../services/message.service';

@Component({
  selector: 'app-b',
  templateUrl: './b.component.html',
})
export class BComponent implements OnInit, OnDestroy {

  receiveMessage: string;

  constructor(private messageService: MessageService) {};

  ngOnInit(): void {
    this.messageService.getMessage().subscribe((value) => {
      this.receiveMessage = value.msg;
    });
  }

  ngOnDestroy(): void {
    this.messageService.close();
  }
}

b.component.ts

Conclusion

To communicate with components in angular by using Subject and Observables you need to:

  • Create a message service for sending and receiving message
  • Send message through the pipe
  • Subscribe to the pipe to receive messages

Be the first to comment

Leave a Reply

Your email address will not be published.


*