Component Communication in Angular

basic · Angular

The Component Data Highway In a component-driven architecture, applications are structured as a hierarchical tree of decoupled visual nodes. For the application to function cohesively, these isolated nodes must pass data and share state changes across parent-child boundaries. To maintain predictable data flows and prevent chaotic state mutations, frameworks enforce a unidirectional data flow pattern : configuration properties flow down from parents to children, while state notification events fire upward from children to parents. Downstream Data Sharing: @Input() The @Input() decorator defines an open data entry gate on a child component. It allows a parent component to pass custom configuration profiles, text strings, arrays, or complete state objects down into a nested child instance. Property Binding Integration: The parent targets the child's declared @Input property name using standard HTML property binding square brackets ( [property]="value" ). Reactive Tracking: Input properties hook natively into change detection lifecycles. When the parent component modifies the bound data variable, the child component automatically receives the updated value. TypeScript // Child Component Logical Controller (job-card.component.ts) import { Component, Input } from '@angular/core'; @Component({ selector: 'app-job-card', standalone: true, template: ` <div class="card"> <h4>{{ jobTitle }}</h4> <p>Company: {{ businessName }}</p> </div> ` }) export class JobCardComponent { // Explicit entry gates for parent data streams @Input() jobTitle: string = ''; @Input('company') businessName: string = ''; // Uses an explicit attribute alias } HTML <app-job-card [jobTitle]="'Full-Stack Developer'" [company]="'THARUN plc'"> </app-job-card> Upstream Notification Systems: @Output() & EventEmitter When an action occurs inside a child component—such as a user clicking a specific button, submitting a local form container, or modifying a localized toggle—the child component cannot mutate parent states directly. Instead, it utilizes the @Output() decorator coupled with an instance of the EventEmitter class to emit a structural signal upward. The Mechanics of EventEmitter EventEmitter is a framework-specific abstraction built on top of RxJS subject streams. It provides an explicit interface to push events out of a component infrastructure. It uses the .emit() method to transmit a data payload. The payload can be a primitive type (like a string or number) or a deeply structured custom object. The parent component intercepts the signal using standard event binding parentheses (outputName)="handleAction($event)" . The special $event keyword captures the exact data packet transmitted by the .emit() method. TypeScript // Child Component Logical Controller (job-card.component.ts) import { Component, Output, EventEmitter } from '@angular/core'; @Component({ selector: 'app-job-card', standalone: true, template: ` <div class="card"> <button (click)="triggerApply()">Apply Now</button> </div> ` }) export class JobCardComponent { // Creating an upstream communication channel routing number payloads @Output() applyClicked = new EventEmitter<number>(); triggerApply() { const mockJobId = 404; this.applyClicked.emit(mockJobId); // Firing the event upward with the payload } } TypeScript // Parent Component Logical Controller (dashboard.component.ts) import { Component } from '@angular/core'; @Component({ selector: 'app-dashboard', standalone: true, template: ` <app-job-card (applyClicked)="processJobApplication($event)"></app-job-card> ` }) export class DashboardComponent { processJobApplication(jobId: number) { console.log(`Parent captured event! Processing application sequence for Job ID: ${jobId}`); } } Modern Alternative: Signal-Based Inputs and Outputs Modern framework engines introduce developer preview primitives that migrate component communication mechanics away from standard decorators and toward fine-grained Signals . This eliminates legacy decorator overhead and unifies reactivity patterns across templates. TypeScript // Modern Signal-Based Component Communication Layout import { Component, input, output } from '@angular/core'; @Component({ selector: 'app-modern-card', standalone: true, template: ` <div class="card"> <h4>Role: {{ roleName() }}</h4> <button (click)="notifyParent()">Select</button> </div> ` }) export class ModernCardComponent { // Read-only Signal property stream (auto-tracks changes without lifecycle checks) roleName = input.required<string>(); // Clean, decorator-free output emitter instance selectionChanged = output<string>(); notifyParent() { this.selectionChanged.emit(this.roleName()); } } Communication Mechanism Comparison Matrix Metric @Input() / input() @Output() / output() Direction of Flow Downward (Parent → Child) Upward (Child → Parent) Template Syntax Property Binding: [childProperty]="parentState" Event Binding: (childEvent)="parentMethod($event)" Data Payload Passes configuration, data models, or primitive state flags down. Transmits action confirmations, execution tracking IDs, or mutated objects up. Primary Purpose Orchestrates component customization and sets internal child parameters. Notifies the ecosystem that a user interaction or state mutation occurred. Underlying Type Standard class property or a reactive Signal wrapper. Managed framework class instance ( EventEmitter ) backed by stream triggers.

Back to Angular

Browse all study material on Careeroza