How to communicate between components
We distinguish several ways of communication between components: parent to child, child to parent and any to any.
In this post I will show an example of the implentation of each of the ways.
Example
The application has three components nav and profile which has a child profile-edit.
1. I would like the name from the profile to be send to the profile edit.
2. When changing name in profile-edit, I would like to pass this value to the parent (profile component).
3. When changing name in profile-edit, I would like to refresh name value in the nav component.

Parent to child
Passing data from parent to child is possible thanks to @Input annotation.
The parent has a defined value name:
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-profile',
templateUrl: './Profile.component.html',
styleUrls: ['./Profile.component.scss']
})
export class ProfileComponent implements OnInit {
name = 'Pawel';
constructor() { }
ngOnInit() {
}
}
Now you must declare input in your child:
import { Component, OnInit, Input } from '@angular/core';
@Component({
selector: 'app-profile-edit',
templateUrl: './Profile-edit.component.html',
styleUrls: ['./Profile-edit.component.scss']
})
export class ProfileEditComponent implements OnInit {
@Input() name: string;
constructor() { }
ngOnInit() {
}
}
Then passing the instance of the profile-edit component in the parent of the name parameter looks like the following:
<app-profile-edit name="{{name}}"></app-profile-edit>
Child to parent
The @Output annotation allows us to achieve the opposite result, pass values from child to parent by using the EventEmitter.
@Output() nameChanged = new EventEmitter<string>();
EventEmitter is a generic type and we can determine what type the parameter will be. In our case – string.
To the button confirming the change of the name I pass the method that will call the event using the emit function
changeName() {
this.nameChanged.emit(this.name);
}
Now, to pass the method that will be triggered when the event is emitted, all you need to do is:
<app-profile-edit (nameChange)="nameChanged($event)"></app-profile-edit>
This will result in calling the nameChanged function of the parent and passing it in the form of an argument – a new name.
Child:
<div class="form-group"> <label>Name</label> <input type="text" class="form-control" [(ngModel)]="name" placeholder="name"> <button class="btn btn-success" (click)="changeName()" style="margin-top:10px;">Change name</button> </div>
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-profile-edit',
templateUrl: './Profile-edit.component.html',
styleUrls: ['./Profile-edit.component.scss']
})
export class ProfileEditComponent implements OnInit {
@Input() name: string;
@Output() nameChanged = new EventEmitter<string>();
constructor() { }
ngOnInit() {
}
changeName() {
this.nameChanged.emit(this.name);
}
}
Parent:
<div class="row" style="margin: 20px;">
<div class="col-md-3">
<div class="card">
<div class="card-body">
<h5 class="card-title">{{name}}</h5>
<p class="card-text">Some information about ..</p>
</div>
</div>
</div>
<div class="col-md-9">
<app-profile-edit name="{{name}}" (nameChange)="nameWasChanged($event)"></app-profile-edit>
</div>
</div>
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-profile',
templateUrl: './Profile.component.html',
styleUrls: ['./Profile.component.scss']
})
export class ProfileComponent implements OnInit {
name = 'Pawel';
constructor() { }
ngOnInit() {
}
nameChanged(name: string) {
this.name = name;
}
}
In this way we can influence the change of the name from the child to the parent.
Any to any
For communication between unrelated components we will need a injectable service which is designed to provide method or properties across to any components. For this purpose I will use the BehaviorSubject which is a type of Observable (can be subscribed to, subscribers can receive updated results and subject is a observer which mean that we can send value to it).
BehaviorSubject needs a initial value, so at first I have to create new service and create new behavior subject from ‘rxjs’.
username = new BehaviorSubject<string>('Pawel');
So the username is now unobservable of type behavior subject so set a currentUsername property as observable.
currentUsername = this.username.asObservable();
We also need to add a method that will update the username in which we call the method next on the observable object which will notify observers about the change of state.
User service:
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class UserService {
username = new BehaviorSubject<string>('Pawel');
currentUsername = this.username.asObservable();
constructor() { }
changeName(username: string) {
this.username.next(username);
}
}
Now in nav component we need to inject userService to subscribe to the currentUsername.
import { UserService } from './../_services/user.service';
import { Component, OnInit } from '@angular/core';
@Component({
selector: 'app-nav',
templateUrl: './nav.component.html',
styleUrls: ['./nav.component.scss']
})
export class NavComponent implements OnInit {
name: string;
constructor(private userService: UserService) { }
ngOnInit() {
this.userService.currentUsername.subscribe(name => this.name = name);
}
}
Then we need to call the changeName method with useservice when changing the name in the profile-edit component.
import { UserService } from './../_services/user.service';
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-profile-edit',
templateUrl: './Profile-edit.component.html',
styleUrls: ['./Profile-edit.component.scss']
})
export class ProfileEditComponent implements OnInit {
@Input() name: string;
@Output() nameChanged = new EventEmitter<string>();
constructor(private userService: UserService) { }
ngOnInit() {
}
changeName() {
this.nameChanged.emit(this.name);
this.userService.changeName(this.name);
}
}
Which means notifying all subscribers of a change in value.
Result:

Whole code available on github.
