Component Communication
Contents
Using Parent-Child Interaction
Parent to Child
Read Data-Binding Section for [(ngModel)]
Parent.HTML
<input type="text" [(ngModel)]="userInput">
<app-child [userInput]="userInput"></app-child>
Child.TS
import { Input } from '@angular/core'; // First, import Input
@Input() userInput : string;
// OR use different alias
@Input('userInput') received_userInput : string;
Child.HTML
<p>{{ received_userInput }}</p>
Child to Parent
Child.HTML
<input
type="text"
[ngModel]=userInput
(ngModelChange)=sendToParent($event)
>
Child.TS
import { Output, EventEmitter } from '@angular/core';
@Output() userInputEmitter = new EventEmitter();
// OR use a alias
@Output('userInput') userInputEmitter = new EventEmitter();
sendToParent(userInput){
this.userInputEmitter.next(userInput);
}
Parent.HTML
<app-child (userInput)=receiveFromChild($event)></app-child>
<p>{{ received_UserInput }}</p>
Parent.TS
received_UserInput : string;
receiveFromChild(userInput){
this.received_UserInput = userInput
}
Using Services
Read RxJS for Subjects and Observables
CommunicationService
// msgEmitter = new EventEmitter<string>();
private msgSubject = new BehaviourSubject('default');
msgObservable = this.msgSubject.asObservable();
passMsg(id : string){
// this.msgEmitter.next(id);
this.msgSubject.next(id);
}
SenderComponent
constructor(
private communicationService: CommunicationService
){}
passId(id){
this.communicationService.passMsg(id);
}
ReceiverComponent
constructor(
private communicationService: CommunicationService
){}
productId : string;
ngOnInit(){
this.communicationService.msgObservable.subscribe(
received_id => {
this.productId = received_id;
}
);
}
Passing reference of component to others
TODO
Using eventemitter3 from npm
- Install EventEmitter3 →
npm i eventemitter3
- Create a service →
EmitterService
- Create an interface for events
- Register all events in a single centralized place
events
to manage easily - Components should emit or subscribe to registered events only
EmitterService
import { Injectable } from "@angular/core";
import { EventEmitter } from "eventemitter3";
// Interface for events
interface Event {
id: string;
info: string;
}
@Injectable({
providedIn: "root",
})
export class EmitterService {
private eventEmitter = new EventEmitter();
on = (event: Event, fn) => this.eventEmitter.on(event.id, fn);
once = (event: Event, fn) => this.eventEmitter.once(event.id, fn);
off = (event: Event, fn) => this.eventEmitter.off(event.id, fn);
emit = (event: Event, payload?) =>
this.eventEmitter.emit(event.id, payload);
events = {
dataFromWingA: {
id: "dataFromWingA",
info: "wingA sends data to wingB",
},
confirmationFromWingB: {
id: "confirmationFromWingB",
info: "wingB sends confirmation",
},
};
constructor() {}
}
- Inject EmitterService and publish events
WingA.HTML
<input type="text" [ngModel]="user_input" (ngModelChange)="sendUserInput($event)" />
WingA.TS
user_input: String;
sendUserInput(input: string) {
this.emitterService.emit(
this.emitterService.events.dataFromWingA,
input
);
}
constructor(private emitterService: EmitterService) {}
ngOnInit() {
this.emitterService.on(
this.emitterService.events.confirmationFromWingB,
() => console.log("OK")
);
}
- Inject and subscribe to events
WingB.HTML
<p>
{{ data_from_WingA }}
</p>
WingB.TS
data_from_WingA: String;
constructor(private emitterService: EmitterService) {}
ngOnInit() {
this.emitterService.on(
this.emitterService.events.dataFromWingA,
(payload) => {
this.emitterService.emit(
this.emitterService.events.confirmationFromWingB
);
this.data_from_WingA = payload;
}
);
}