Understanding EventEmitter in Angular: A Complete Guide

EventEmitter in Angular is a class used for emitting custom events synchronously or asynchronously, and it is a crucial part of Angular's component interaction mechanism. It allows child components to send data to their parent components. This is especially useful in scenarios where a direct data binding (using @Input) from parent to child isn't sufficient, particularly when the child component needs to send some data back up to the parent or notify the parent of an event.

Why We Need to Use EventEmitter

  1. Component Communication: In Angular, components often need to communicate with each other. While @Input allows data to flow down from parent to child, EventEmitter with @Output allows data to flow from child to parent.

  2. Custom Events: It enables components to emit custom events. This is useful when you want a component to react to specific actions taken in another component.

  3. Decoupling Components: It helps in decoupling components by reducing the direct dependency between components, making the application more modular and easier to manage.

Real-World Example

Imagine an e-commerce application with a component for a product list and another component for a shopping cart. The product list component displays products, and each product has an "Add to Cart" button.

Objective: When a user clicks "Add to Cart" on a product, the product list component needs to notify the shopping cart component to add the product.

Solution Using EventEmitter:

  1. Product Component (Child): It emits an event when a product is added to the cart.
  2. Shopping Cart Component (Parent): It listens for the event and updates the cart accordingly.

Step-by-Step Implementation

  1. Product Component (Child):
    • It has an @Output() property that is an instance of EventEmitter.
    • When the "Add to Cart" button is clicked, it emits an event with the product information.
// In product.component.ts
import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'app-product',
  template: `<button (click)="addToCart()">Add to Cart</button>`
})
export class ProductComponent {
  @Output() productAdded = new EventEmitter<any>();

  addToCart() {
    const productData = {/* product details */};
    this.productAdded.emit(productData);
  }
}
  1. Shopping Cart Component (Parent):
    • It listens for the productAdded event from the Product Component.
    • When the event is received, it updates the shopping cart.
// In shopping-cart.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-shopping-cart',
  template: ``
})
export class ShoppingCartComponent {
  updateCart(product: any) {
    // Logic to add product to cart
  }
}
  1. Parent Component's Template:
    • The parent component's template binds the productAdded event to the updateCart() method.
<!-- In parent component's template -->
<app-product (productAdded)="updateCart($event)"></app-product>

This example illustrates how EventEmitter facilitates component communication in Angular, allowing for a more modular and manageable application structure.