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
productAddedevent.
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()withEventEmitter. The parent listens using event binding, such as(productAdded)="onProductAdded($event)", where $event contains the value emitted by the child.