How to communicate and share data from parent component to child component (@Input decorators) and from child component to parent component (@Output decorators).
Introduction
- Angular provides data sharing decorators to communicate between the parent component to the child component using the @Input decorator and from the child component to the parent component using the @Output decorator,
- Here @Input() property is writable and an @Output() property is observable.
- So let's understand more by using the examples below.
@Input decorator
parent.component.html
<div class="wrapper">
<app-child
[dataFromParent]="passDataFromParent"
></app-child>
</div>
child.component.ts
import { Component, Input, OnInit } from '@angular/core';
import { ChildData } from '../../SAMPLE_DATA';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss'],
})
export class ChildComponent implements OnInit {
@Input() dataFromParent!: ChildData[];
}
child.component.html
<h2>Child Component</h2>
<div class="child-wrapper">
<ng-container *ngFor="let item of dataFromParent">
<mat-card align="center">
<mat-card-content> {{ item.name }} </mat-card-content>
<button
mat-raised-button
color="primary">
Select
</button>
</mat-card>
</ng-container>
</div>
We show passing data from the parent component to the child component.
The output of @Input decorator example
As you can see here, I clicked any food products and passed that data from the parent component to the child component and the child component displayed those data in card format.
@Output decorator
child.component.html
<h2>Child Component</h2>
<div class="child-wrapper">
<ng-container *ngFor="let item of dataFromParent">
<mat-card align="center">
<mat-card-content> {{ item.name }} </mat-card-content>
<button
mat-raised-button
color="primary"
(click)="passDataToParent(item)"
>
Select
</button>
</mat-card>
</ng-container>
</div>
child.component.ts
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { ChildData } from '../../SAMPLE_DATA';
@Component({
selector: 'app-child',
templateUrl: './child.component.html',
styleUrls: ['./child.component.scss'],
})
export class ChildComponent implements OnInit {
@Input() dataFromParent!: ChildData[];
@Output() onClick = new EventEmitter();
constructor() {}
ngOnInit(): void {}
passDataToParent(item: ChildData) {
this.onClick.emit(item);
}
}
- Now in the parent component template, I bind the parent method getDataFromChild($event) to the child component onClick event to get emitted event from the child component
- So Using the (onClick) output event, the parent component receives a response event from the child component in the getDataFromChild() method, stores it in the dataFromChild variable, and displays it as a Selected Item:
parent.component.html
<div class="wrapper">
<h2>Parent Component</h2>
<div class="title">
Selected Item :
<span *ngIf="dataFromChild" class="selected-item">
{{ dataFromChild?.name }}
</span>
</div>
<ng-container *ngFor="let item of sampleData">
<button
mat-flat-button
color="warn"
style="margin-right: 12px"
(click)="passDataToChild(item.childData)"
>
{{ item.name }}
</button>
</ng-container>
</div>
<div class="wrapper">
<app-child
[dataFromParent]="passDataFromParent"
(onClick)="getDataFromChild($event)"
></app-child>
</div>
parent.component.ts
import { Component, Input, OnInit } from '@angular/core';
import { ChildData, ParentData, SAMPLE_DATA } from '../../SAMPLE_DATA';
@Component({
selector: 'app-parent',
templateUrl: './parent.component.html',
styleUrls: ['./parent.component.scss'],
})
export class ParentComponent implements OnInit {
passDataFromParent!: ChildData[];
dataFromChild: ChildData | undefined;
sampleData = SAMPLE_DATA.parentData;
constructor() {}
ngOnInit(): void {}
getDataFromChild(item: ChildData) {
this.dataFromChild = item;
}
passDataToChild(item: ChildData[]) {
this.dataFromChild = undefined;
this.passDataFromParent = item;
}
}
- If you want to pass a specific data type in the output decorator, you can do so as shown above.
The Output of @Output decorator example
As you can see here I select any food item by clicking on it, and the child component emits that selected data to the parent component, which reads that data and displays it as Selected Item
The final output
- Find the full source code here
Summary
- As you can see, this blog covers how to pass or emit events carrying data from a child component to a parent component using the @Output decorator, as well as how to send data from a parent component to a child component using the @Input decorator.
- Please let me know in the comments area if you have any questions.