Skip to main content
Angular Basics
CHAPTER 17 Beginner

Component Communication

Updated: May 18, 2026
5 min read

# CHAPTER 17

Component Communication

1. Chapter Introduction

In a real Angular app, components cannot live in isolation. A parent component may pass a user object down to a child profile card. A child delete button may need to notify the parent to remove an item. Components need structured communication channels. Angular provides three main patterns: @Input, @Output with EventEmitter, and service-based (shared state) communication.

2. Learning Objectives

  • Pass data from parent to child using @Input.
  • Send events from child to parent using @Output and EventEmitter.
  • Share state between non-related components using a Service.
  • Understand @ViewChild for direct child access.

3. @Input — Parent to Child

parent.component.ts
123
export class ParentComponent {
  selectedProduct = { id: 1, name: 'Laptop', price: 999 };
}
html
12
<!-- parent.component.html -->
<app-product-card [product]="selectedProduct"></app-product-card>
product-card.component.ts
1234567891011121314
import { Component, Input } from &#039;@angular/core&#039;;

@Component({
  selector: &#039;app-product-card&#039;,
  template: `
    <div class="card">
      <h3>{{ product.name }}</h3>
      <p>${{ product.price }}</p>
    </div>
  `
})
export class ProductCardComponent {
  @Input() product: any; // Receives data from parent
}

4. @Output — Child to Parent

delete-btn.component.ts
12345678910111213141516
import { Component, Input, Output, EventEmitter } from &#039;@angular/core&#039;;

@Component({
  selector: &#039;app-delete-btn&#039;,
  template: `<button (click)="onDelete()">Delete {{ itemName }}</button>`
})
export class DeleteBtnComponent {
  @Input() itemId!: number;
  @Input() itemName: string = &#039;&#039;;

  @Output() itemDeleted = new EventEmitter<number>();

  onDelete(): void {
    this.itemDeleted.emit(this.itemId); // Sends event UP to parent
  }
}
html
123456
<!-- parent.component.html -->
<app-delete-btn
  [itemId]="product.id"
  [itemName]="product.name"
  (itemDeleted)="handleDelete($event)">
</app-delete-btn>
parent.component.ts
12345678
export class ParentComponent {
  products = [...];

  handleDelete(productId: number): void {
    this.products = this.products.filter(p => p.id !== productId);
    console.log(&#039;Product deleted:&#039;, productId);
  }
}

5. Service-Based Communication (Siblings)

When two components have no direct parent-child relationship, a shared service with a Subject or BehaviorSubject is the clean solution:
notification.service.ts
123456789101112
import { Injectable } from &#039;@angular/core&#039;;
import { Subject } from &#039;rxjs&#039;;

@Injectable({ providedIn: &#039;root&#039; })
export class NotificationService {
  private messageSource = new Subject<string>();
  message$ = this.messageSource.asObservable();

  sendMessage(message: string): void {
    this.messageSource.next(message);
  }
}
sender.component.ts
1234
export class SenderComponent {
  constructor(private notifService: NotificationService) {}
  sendAlert(): void { this.notifService.sendMessage(&#039;Item saved successfully!&#039;); }
}
receiver.component.ts
1234567891011
export class ReceiverComponent implements OnInit, OnDestroy {
  notification: string = &#039;&#039;;
  private sub!: Subscription;

  constructor(private notifService: NotificationService) {}

  ngOnInit(): void {
    this.sub = this.notifService.message$.subscribe(msg => this.notification = msg);
  }
  ngOnDestroy(): void { this.sub.unsubscribe(); }
}

6. @ViewChild — Direct Child Access

typescript
12345678910
import { ViewChild, AfterViewInit } from &#039;@angular/core&#039;;
import { CounterComponent } from &#039;./counter/counter.component&#039;;

export class ParentComponent implements AfterViewInit {
  @ViewChild(CounterComponent) counterChild!: CounterComponent;

  ngAfterViewInit(): void {
    console.log(&#039;Child count:&#039;, this.counterChild.count);
  }
}

7. Communication Pattern Summary

text
12345
Parent → Child:       @Input()
Child → Parent:       @Output() + EventEmitter
Sibling → Sibling:    Shared Service + Subject
Parent ↔ Child:       @ViewChild (direct access)
Any → Any:            Shared Service + BehaviorSubject

8. Common Mistakes

  • Mutating @Input data directly: Never modify an @Input property inside the child component. This breaks data flow and causes unpredictable bugs. Instead, emit an event and let the parent handle the change.
  • EventEmitter for non-component communication: EventEmitter is designed for template events only. For service-to-service or sibling communication, use RxJS Subject.

9. MCQs with Answers

Question 1

Which decorator allows a child component to receive data from its parent?

Question 2

Which decorator allows a child component to emit events to its parent?

Question 3

What class is used alongside @Output to emit events?

Question 4

In (itemDeleted)="handleDelete($event)", what does $event contain?

Question 5

What is the best pattern for communication between two sibling components with no parent-child relationship?

Question 6

What decorator gives a parent direct access to a child component instance?

Q7. Should you directly modify an @Input property inside the child component? a) Yes b) No — emit an event via @Output and let the parent handle modification Answer: b) No — use @Output.
Question 8

When is @ViewChild available to use?

Question 9

How do you pass a string "hello" from parent to a child's @Input() message property?

Question 10

What is the recommended solution for app-wide state sharing between many unrelated components?

10. Interview Questions

  • Q: Explain the difference between @Input/@Output and service-based communication. When would you choose one over the other?
  • Q: What is the difference between Subject and BehaviorSubject for component communication?

11. Summary

Angular's component communication system is elegant and predictable. @Input creates a data downflow from parent to child. @Output creates an event upflow from child to parent. Services with RxJS Subjects bridge the gap for any other communication scenario. Following these patterns strictly keeps your component architecture clean and decoupled.

12. Next Chapter Recommendation

As applications grow, managing state across many components becomes complex. In Chapter 18: State Management Basics, we explore patterns for managing application state, from simple service-based state to an introduction of NgRx.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·