How to communicate and share data from parent component to child component (@Input decorators) and from child component to parent component (@Output decorators).

Introduction

@Input decorator

parent.component.html

HTML / XML
<div class="wrapper">
  <app-child
    [dataFromParent]="passDataFromParent"
  ></app-child>
</div>

child.component.ts

JavaScript
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

HTML / XML
<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.

@Input decorator

@Output decorator

child.component.html

HTML / XML
<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

JavaScript
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);
  }
}

parent.component.html

HTML / XML
<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

JavaScript
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;
  }
}

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

@Ouput decorator

The final output

Angular Input & Output Decorator

Summary