π Component Communication in Angular
How Components Talk to Each Other (Like Family Members!)
π The Family Metaphor
Imagine your Angular app is a house with family members living in different rooms.
- Parent Component = Mom or Dad (the boss!)
- Child Component = Kids (they listen AND speak up!)
- Service = The family phone (everyone can use it to talk!)
Components need to share information. Just like family members call each other for dinner or ask for help with homework!
π¬ What is Component Communication?
In Angular, your app is made of components. Each component is like a LEGO brick. They need to share data and send messages to work together.
Real Life Example:
- A shopping cart page has a Product List (parent)
- Each Product Card is a child
- When you click βAdd to Cartβ, the child tells the parent!
graph TD A[Parent Component] -->|Sends Data Down| B[Child Component] B -->|Sends Events Up| A
β¬οΈ The @Input Decorator
Sending Data DOWN (Parent β Child)
Think of @Input like a gift box that parents give to their children.
Simple Example:
Parent says: βHereβs your allowance money!β
Child receives: The money in their @Input pocket.
Code Example:
child.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child',
template: `<p>My name is {{ name }}</p>`
})
export class ChildComponent {
@Input() name: string = '';
}
parent.component.html
<app-child [name]="'Tommy'"></app-child>
What Happens?
- Parent has data:
'Tommy' - Parent passes it to child using
[name] - Child receives it in
@Input() name - Child displays: βMy name is Tommyβ
π― Key Point:
Data flows DOWN like water falling from a waterfall!
β¬οΈ The @Output Decorator
Sending Events UP (Child β Parent)
Think of @Output like a walkie-talkie that children use to call their parents.
Simple Example:
Child says: βMom! I finished my homework!β
Parent hears: The message through @Output!
Code Example:
child.component.ts
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child',
template: `
<button (click)="sendMessage()">
Tell Parent!
</button>
`
})
export class ChildComponent {
@Output() notify = new EventEmitter<string>();
sendMessage() {
this.notify.emit('Hello from child!');
}
}
parent.component.html
<app-child (notify)="onNotify($event)">
</app-child>
parent.component.ts
onNotify(message: string) {
console.log(message);
// Prints: "Hello from child!"
}
π― Key Point:
Events flow UP like bubbles rising in water!
π’ EventEmitter
The Magic Messenger!
EventEmitter is the actual messenger that carries your message from child to parent.
Think of it like a paper airplane that flies from the childβs room to the parentβs room!
How It Works:
graph LR A[Child clicks button] --> B[EventEmitter.emit] B --> C[Message flies UP] C --> D[Parent catches it]
Three Steps:
- Create the emitter:
@Output() buttonClicked = new EventEmitter<string>();
- Send a message:
this.buttonClicked.emit('I was clicked!');
- Listen in parent:
<app-child (buttonClicked)="handleClick($event)">
</app-child>
You Can Send Anything!
- Strings:
emit('hello') - Numbers:
emit(42) - Objects:
emit({id: 1, name: 'Tom'})
π§ Smart vs Dumb Components
The Brain and The Body!
Imagine your body:
- Brain = Smart Component (thinks, makes decisions)
- Hands = Dumb Component (just does what brain says)
Smart Components (Container Components)
These are the bosses. They:
- β Talk to services
- β Fetch data from APIs
- β Make decisions
- β Pass data to dumb components
Dumb Components (Presentational Components)
These are the workers. They:
- β Just display data
- β Receive data via @Input
- β Send events via @Output
- β Donβt know where data comes from
Visual Example:
graph TD A[Smart: UserListContainer] -->|users array| B[Dumb: UserCard] A -->|users array| C[Dumb: UserCard] B -->|delete event| A C -->|delete event| A A <-->|fetch users| D[UserService]
Code Example:
Smart Component (knows everything)
@Component({
selector: 'app-user-list',
template: `
<app-user-card
*ngFor="let user of users"
[user]="user"
(delete)="onDelete($event)">
</app-user-card>
`
})
export class UserListComponent {
users: User[] = [];
constructor(private userService: UserService) {
this.users = this.userService.getUsers();
}
onDelete(userId: number) {
this.userService.delete(userId);
}
}
Dumb Component (just shows data)
@Component({
selector: 'app-user-card',
template: `
<div class="card">
<h3>{{ user.name }}</h3>
<button (click)="onDeleteClick()">
Delete
</button>
</div>
`
})
export class UserCardComponent {
@Input() user!: User;
@Output() delete = new EventEmitter<number>();
onDeleteClick() {
this.delete.emit(this.user.id);
}
}
π― Why This Pattern?
| Benefit | Explanation |
|---|---|
| Reusable | Dumb components work anywhere! |
| Testable | Easy to test separately |
| Clean | Clear separation of jobs |
| Maintainable | Easy to fix and update |
π Service Communication
The Family Phone Everyone Can Use!
What if two components are NOT parent-child? Like two cousins who live in different houses?
Solution: Use a SERVICE!
A service is like a phone line that any component can call!
graph TD A[Component A] <-->|calls| S[Shared Service] B[Component B] <-->|calls| S C[Component C] <-->|calls| S
Simple Service Example:
message.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class MessageService {
private message = new BehaviorSubject<string>('Hello!');
currentMessage = this.message.asObservable();
changeMessage(newMessage: string) {
this.message.next(newMessage);
}
}
sender.component.ts
@Component({
selector: 'app-sender',
template: `
<button (click)="send()">
Send Message
</button>
`
})
export class SenderComponent {
constructor(private msgService: MessageService) {}
send() {
this.msgService.changeMessage('Hi from Sender!');
}
}
receiver.component.ts
@Component({
selector: 'app-receiver',
template: `<p>{{ message }}</p>`
})
export class ReceiverComponent {
message: string = '';
constructor(private msgService: MessageService) {
this.msgService.currentMessage.subscribe(
msg => this.message = msg
);
}
}
What Happens?
- Sender clicks button
- Service updates the message
- Receiver automatically gets the new message
- Magic! π
π― Quick Summary
| Method | Direction | Use Case |
|---|---|---|
@Input |
Parent β Child | Pass data down |
@Output |
Child β Parent | Send events up |
EventEmitter |
With @Output | The messenger |
| Smart Component | N/A | Handles logic & data |
| Dumb Component | N/A | Just displays |
| Service | Any β Any | Unrelated components |
π Remember The Family!
Parent (Smart) gives gifts β @Input β Child (Dumb) receives
Child (Dumb) sends message β @Output + EventEmitter β Parent hears
Cousins talk β Service β Everyone connected!
You now understand how Angular components talk to each other!
The house is harmonious. Everyone communicates. Your app works beautifully! π β¨