DEV Community

Cover image for 🅰️ Angular Fundamentals: Mastering Component Communication with @Input and @Output
Md Habibur Rahman
Md Habibur Rahman

Posted on

🅰️ Angular Fundamentals: Mastering Component Communication with @Input and @Output

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) { ... }
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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);
  }
}
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

🔑 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?

#Angular #AngularTips #Frontend #WebDev

Top comments (0)