In this article, I am going to cover communication between components via inputs, outputs and event emitters.
Output should be used to send/receive data between a child and parent component. Input is leveraged to receive data from a parent component, and Output is leveraged to send data to the parent component.
Parent to Child Communication: Input
When dealing with a situation where the parent component needs to pass data to a child component, use the Input property. The Input property is the base level communication from a parent component to a child component.
Below is an example child component with a text input property.
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<h3>Hello, {{ text }}</h3>
`
})
export class AppChildComponent {
@Input()
text = '';
}
In the above example, a text Input property is declared and set to an empty string. The value can be changed within the child component or within the parent component.
<app-child text="Ryan"></app-child>
Input properties can be intercepted with a setter, or within ngOnChanges, in order to perform manipulation on the value. In the below example, we take the text Input property and add an exclamation point to the string.
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<h3>Hello, {{ text }}</h3>
`
})
export class AppChildComponent {
@Input()
get text() {
return this._text;
}
set text(val: string) {
this._text = val ? `${val.trim()}!`: 'World!';
}
private _text = '';
}
In the below example, we do the exact same operation as the above example, but leverage ngOnChanges.
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<h3>Hello, {{ text }}</h3>
`
})
export class AppChildComponent {
@Input()
text = '';
ngOnChanges(changes: SimpleChanges) {
if(changes.text) {
if(this.text) {
this.text = this.text ? `${this.text.trim()}!`: 'World!';
}
}
}
}
Both examples perform the same functionality, but do it in different ways. Some developers prefer to leverage ngOnChanges when interacting with multiple Input properties.
Child to Parent Communication: Output
When dealing with a situation where the child component needs to pass data to the parent component, use the Output property. The Output property is the base level communication from a child component to the parent component. The Output property is generally used in situations where the child component needs to trigger a method on a parent component.
A good example would be when the child component has a button on it that the parent component will perform an action when clicked.
import { Component, EventEmitter, Output } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button type="button" (click)="_onButtonClick()">Test</button>
`
})
export class AppChildComponent {
@Output()
buttonClick = new EventEmitter<string>();
_onButtonClick() {
this.buttonClick.emit('test button click value');
}
}
import { Component } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<app-child (buttonClick)="_onChildButtonClick($event)"></app-child>
`
})
export class AppChildComponent {
_onChildButtonClick(childValue: string) {
console.log(`Child component emitted ${childValue}`);
}
}