← Back to Articles         
Pass Data from Child to Parent

Pass Data from Child to Parent

Published on 29 Sep 2026     9 min read Angular
Angular Components

1. How Do You Pass Data from Child to Parent in Angular?

What is Child-to-Parent Communication?

When a child component needs to send information or notify its parent that something happened, Angular uses output events.

Modern Angular uses the output() API:

productAdded = output<string>();

Traditional Angular applications commonly use @Output() with EventEmitter:

@Output()
productAdded = new EventEmitter<string>();

The basic flow is:

Child Component
      │
      │ emit(...)
      ▼
Output Event
      │
      │ (productAdded)
      ▼
Parent Component

Why Do We Need It?

Consider a Product child component:

ProductList (Parent)
       │
       ▼
Product (Child)
       │
       └── Add to Cart button

The button exists in the child, but the parent may need to know which product was selected.

For example:

User clicks "Add to Cart"
          │
          ▼
     Product Child
          │
          │ Emits product
          ▼
     ProductList Parent
          │
          ▼
   Updates cart

The child should not directly manipulate the parent's internal state. Instead, it emits an event and lets the parent decide what to do.


Purpose

Child-to-parent communication is commonly used when a child needs to report:

  • Button clicks
  • Form submission
  • Selected item
  • Deleted item
  • Changed value
  • Save/cancel action
  • User interaction
  • Custom component events

For example:

Child                     Parent

Product                    ProductList
   │                           ▲
   │ productAdded              │
   └───────────────────────────┘

Code Sample – Modern Angular

Suppose:

ProductList → Parent
Product     → Child

The child has an Add to Cart button.

Child – product.ts

import { Component, output } from '@angular/core';

@Component({
  selector: 'app-product',
  templateUrl: './product.html'
})
export class Product {

  productAdded = output<string>();

  addToCart() {
    this.productAdded.emit('Laptop');
  }
}

Child – product.html

<button (click)="addToCart()">
  Add to Cart
</button>

Parent – product-list.ts

import { Component } from '@angular/core';
import { Product } from '../product/product';

@Component({
  selector: 'app-product-list',
  imports: [Product],
  templateUrl: './product-list.html'
})
export class ProductList {

  onProductAdded(product: string) {
    console.log('Added:', product);
  }
}

Parent – product-list.html

<app-product
  (productAdded)="onProductAdded($event)">
</app-product>

Code Explanation

Step 1 – Child Creates an Output

productAdded = output<string>();

This creates an output event named:

productAdded

The <string> means the event emits a string value.


Step 2 – User Clicks the Button

<button (click)="addToCart()">
  Add to Cart
</button>

Angular calls:

addToCart()

Step 3 – Child Emits the Event

this.productAdded.emit('Laptop');

The child emits:

Laptop

through the productAdded output.

Child

productAdded.emit("Laptop")
           │
           ▼
     productAdded event

Step 4 – Parent Listens to the Event

The parent uses:

<app-product
  (productAdded)="onProductAdded($event)">
</app-product>

The parentheses:

( )

represent event binding.

Therefore:

(productAdded)

means:

Listen for the child's productAdded event.


Step 5 – $event Contains the Emitted Data

The child emits:

this.productAdded.emit('Laptop');

Therefore:

$event = "Laptop"

The parent receives it:

onProductAdded(product: string) {
  console.log(product);
}

Output:

Laptop

Complete Flow

                CHILD COMPONENT
                    Product
                       │
                       │
             User clicks button
                       │
                       ▼
                  addToCart()
                       │
                       ▼
      productAdded.emit("Laptop")
                       │
                       │
                       ▼
              productAdded event
                       │
                       │
                       ▼
                PARENT TEMPLATE

(productAdded)="onProductAdded($event)"
                       │
                       ▼
                  $event
                       │
                       ▼
                   "Laptop"
                       │
                       ▼
                PARENT COMPONENT

           onProductAdded("Laptop")

This is the most important flow to understand.


Passing an Object from Child to Parent

In real applications, we often send an entire object rather than just a string.

Suppose:

export interface ProductModel {
  id: number;
  name: string;
  price: number;
}

Child

export class Product {

  productAdded = output<ProductModel>();

  addToCart() {

    const product: ProductModel = {
      id: 1,
      name: 'Laptop',
      price: 50000
    };

    this.productAdded.emit(product);
  }
}

Parent:

<app-product
  (productAdded)="onProductAdded($event)">
</app-product>

Parent TypeScript:

onProductAdded(product: ProductModel) {
  console.log(product.name);
  console.log(product.price);
}

Flow:

Child
  │
  │ emit(product)
  ▼
{
  id: 1,
  name: "Laptop",
  price: 50000
}
  │
  ▼
Parent

2. What Are Output Events?

What is an Output Event?

An output event is a custom event exposed by a child component so that its parent can listen for an action or receive data from the child.

Modern Angular:

productAdded = output<string>();

Parent listens:

<app-product
  (productAdded)="onProductAdded($event)">
</app-product>

Purpose of Output Events

Outputs allow a child to notify its parent without tightly coupling the child to the parent's implementation.

For example, the child says:

"A product was selected."

It doesn't need to know what the parent will do afterward.

The parent might:

Product selected
       │
       ▼
Parent
       │
       ├── Add to cart
       ├── Show notification
       ├── Update total
       └── Log activity

This keeps the child reusable.


Input vs Output

This is one of the most important Angular concepts.

              PARENT
                 │
                 │ Input
                 ▼
               CHILD
                 │
                 │ Output
                 ▼
              PARENT
Input Output
Parent → Child Child → Parent
Receives data Emits events/data
input() output()
@Input() traditional @Output() traditional
[product] (productAdded)

Easy way to remember:

INPUT
Data goes INTO child.

OUTPUT
Event comes OUT OF child.

Property Binding vs Event Binding

Parent → Child:

<app-product
  [product]="selectedProduct">
</app-product>

Square brackets:

[ ]

mean property binding.

Child → Parent:

<app-product
  (productAdded)="onProductAdded($event)">
</app-product>

Parentheses:

( )

mean event binding.

Remember:

[property] → Data

(event)    → Event

3. What is EventEmitter?

What is EventEmitter?

EventEmitter is an Angular class traditionally used together with @Output() to emit custom events from a child component to its parent.

It is imported from:

import { EventEmitter } from '@angular/core';

Usually you'll see:

import {
  Component,
  EventEmitter,
  Output
} from '@angular/core';

Why Do We Need EventEmitter?

Before the newer output() API, the standard Angular pattern for child-to-parent communication was:

@Output()
productAdded = new EventEmitter<string>();

The child then emits:

this.productAdded.emit('Laptop');

The parent listens:

<app-product
  (productAdded)="onProductAdded($event)">
</app-product>

You need to understand this pattern because it is extremely common in existing Angular applications.


Full EventEmitter Example

Child

import {
  Component,
  EventEmitter,
  Output
} from '@angular/core';

@Component({
  selector: 'app-product',
  templateUrl: './product.html'
})
export class Product {

  @Output()
  productAdded = new EventEmitter<string>();

  addToCart() {
    this.productAdded.emit('Laptop');
  }
}

Child HTML:

<button (click)="addToCart()">
  Add to Cart
</button>

Parent

import { Component } from '@angular/core';
import { Product } from '../product/product';

@Component({
  selector: 'app-product-list',
  imports: [Product],
  templateUrl: './product-list.html'
})
export class ProductList {

  onProductAdded(product: string) {
    console.log('Added:', product);
  }
}

Parent HTML:

<app-product
  (productAdded)="onProductAdded($event)">
</app-product>

Understanding the Three Important Parts

The traditional syntax has three important pieces.

1. @Output()

@Output()

Marks the property as an output exposed by the component.


2. EventEmitter

new EventEmitter<string>()

Creates the event emitter.

string specifies the type of data that will be emitted.

For example:

new EventEmitter<string>()

emits strings.

new EventEmitter<number>()

emits numbers.

new EventEmitter<ProductModel>()

emits ProductModel objects.


3. emit()

this.productAdded.emit('Laptop');

Actually fires/emits the event.

Therefore:

@Output()
    │
    ▼
EventEmitter<string>
    │
    ▼
emit("Laptop")
    │
    ▼
Parent receives "Laptop"

output() vs @Output() + EventEmitter

Modern Angular provides a simpler output API.

Modern

productAdded = output<string>();

Emit:

this.productAdded.emit('Laptop');

Traditional

@Output()
productAdded = new EventEmitter<string>();

Emit:

this.productAdded.emit('Laptop');

Parent syntax is essentially the same:

<app-product
  (productAdded)="onProductAdded($event)">
</app-product>

Comparison

Feature Modern output() Traditional EventEmitter
Child → Parent Yes Yes
Declaration output<T>() @Output() EventEmitter<T>
Emit .emit() .emit()
Parent binding (event) (event)
Modern API Yes Older/decorator API
Existing codebases Increasing Very common
Need @Output() No Yes

For new Angular code, the modern output() API is generally the cleaner approach, while @Output() + EventEmitter remains important for maintaining and understanding existing applications.


Advantages

Clear Communication

It clearly represents:

Child → Parent

Loose Coupling

The child doesn't need to directly manipulate the parent.

Reusable Components

The parent decides what to do when the event occurs.

Type Safety

You can define:

output<string>()
output<number>()
output<ProductModel>()

or:

new EventEmitter<ProductModel>()

Easy Event Handling

The syntax follows Angular's familiar event-binding style:

(productAdded)="onProductAdded($event)"

Disadvantages

Too Many Outputs

A component with many outputs can become difficult to maintain:

saved = output<void>();
deleted = output<number>();
selected = output<Product>();
cancelled = output<void>();
changed = output<Product>();

This may indicate that the component's responsibilities should be reconsidered.

Deep Component Hierarchies

Passing events through several layers can become cumbersome:

Child D
   ↓
Parent C
   ↓
Parent B
   ↓
Parent A

For communication across distant/unrelated components, a shared service or state-management approach may be more appropriate.

EventEmitter Is Angular-Specific

EventEmitter is an Angular abstraction intended primarily for component/directive outputs. It should not be treated as a general-purpose application event bus.

For service-level reactive communication, Signals or RxJS are usually more appropriate.


Key Points

Parent → Child

Modern:

product = input<ProductModel>();

Traditional:

@Input()
product!: ProductModel;

Child → Parent

Modern:

productAdded = output<ProductModel>();

Traditional:

@Output()
productAdded = new EventEmitter<ProductModel>();

Emit Data

this.productAdded.emit(product);

Parent Receives Data

<app-product
  (productAdded)="onProductAdded($event)">
</app-product>

$event

Contains the value emitted by the child:

Child

emit("Laptop")
      │
      ▼
   $event
      │
      ▼
 "Laptop"
      │
      ▼
Parent

Most Important Diagram

                 PARENT COMPONENT

              selectedProduct
                     │
                     │
        [product]="selectedProduct"
                     │
                     ▼
                 CHILD COMPONENT
                     │
                     │
             User clicks Add
                     │
                     ▼
         productAdded.emit(product)
                     │
                     ▼
                 OUTPUT EVENT
                     │
                     ▼
                 PARENT

(productAdded)="onProductAdded($event)"
                     │
                     ▼
                  $event

So the complete communication pattern is:

Parent
   │
   │ Input
   ▼
Child
   │
   │ Output
   ▼
Parent

Interview Questions & Answers

Q1. How do you pass data from child to parent?

The child exposes an output event, emits a value, and the parent listens to that event.

Modern:

productAdded = output<string>();
this.productAdded.emit('Laptop');

Parent:

<app-product
  (productAdded)="onProductAdded($event)">
</app-product>

Q2. What is an output event?

An output event is a custom event exposed by a child component that allows the child to notify its parent or send data to it.


Q3. What is EventEmitter?

EventEmitter is an Angular class traditionally used with @Output() to emit custom component events.

@Output()
productAdded = new EventEmitter<string>();

Q4. What does emit() do?

emit() fires the output event and optionally sends a value.

this.productAdded.emit('Laptop');

Here the emitted value is "Laptop".


Q5. What is $event?

$event contains the value emitted by the child.

If:

this.productAdded.emit('Laptop');

then:

(productAdded)="onProductAdded($event)"

passes "Laptop" to onProductAdded().


Q6. What is the difference between @Input() and @Output()?

@Input() @Output()
Parent → Child Child → Parent
Receives data Emits event/data
Property binding [ ] Event binding ( )

Q7. What is the difference between output() and EventEmitter?

output() is the newer Angular API for declaring component outputs. EventEmitter is the traditional approach and is normally used with @Output().

Modern:

saved = output<string>();

Traditional:

@Output()
saved = new EventEmitter<string>();

Both allow the parent to listen using:

(saved)="onSaved($event)"

Q8. Should EventEmitter be used inside Angular services?

Generally, no. EventEmitter is primarily intended for component/directive outputs. For shared service state or event streams, prefer Signals or RxJS, depending on the requirement.


Interview-Ready Answer

For child-to-parent communication, the child exposes an output event and emits data when an action occurs. In modern Angular this is done with output(). In traditional Angular it is done using @Output() with EventEmitter. The parent listens using event binding, such as (productAdded)="onProductAdded($event)", where $event contains the value emitted by the child.

← Back to Articles