Component communication is a core skill for building scalable Angular applications. While there are many ways to share data (services, RxJS), the most fundamental and robust method for direct interaction between components is the Parent-Child pattern using @Input
and @Output
.
This pattern enforces Unidirectional Data Flow, making your applications more predictable and easier to debug.
1. Passing Data Down: The @Input()
Decorator
The @Input()
decorator allows a parent component to inject data into a property of its child component. This is the standard mechanism for configuration and data binding.
In the Child Component (user-details.component.ts
):
We declare a property and decorate it with @Input()
:
import { Component, Input } from '@angular/core';
@Component({...})
export class UserDetailsComponent {
// The property that receives data from the parent
@Input() userProfile: { name: string, role: string };
// Note: Using a setter is a common pattern to run code whenever the input changes
// @Input() set userId(value: string) { ... }
}
In the Parent Component (app.component.html
):
The parent binds its own data property (activeUser
) to the child's input property (userProfile
):
<app-user-details [userProfile]="activeUser"></app-user-details>
The data flows down from parent to child.
2. Passing Events Up: The @Output()
Decorator
The @Output()
decorator allows a child component to send a notification (an event) to its parent component, often carrying a payload of data. This ensures the child component remains self-contained and doesn't directly manipulate its parent.
In the Child Component (user-details.component.ts
):
We declare a property decorated with @Output()
and initialize it with an EventEmitter
.
import { Component, Output, EventEmitter } from '@angular/core';
@Component({...})
export class UserDetailsComponent {
// The event emitter that the parent can listen to
// Specifies that a boolean (or any type) will be emitted
@Output() profileSaved = new EventEmitter<boolean>();
saveProfile() {
// When a button is clicked or some action completes, we emit the event
this.profileSaved.emit(true);
}
}
In the Parent Component (app.component.html
):
The parent listens for the event emitted by the child and calls one of its own methods (handleSave
).
<app-user-details
[userProfile]="activeUser"
(profileSaved)="handleSave($event)"> </app-user-details>
🔑 Key Principle: Unidirectional Flow
Always strive to pass data down via @Input
and communicate actions up via @Output
. This creates a clean, predictable hierarchy. If you ever need complex, cross-component communication (siblings, cousins), that's when a shared Service with RxJS Subjects is the appropriate solution.
What methods do you prefer for handling highly complex communication flows in large Angular applications?
Top comments (0)