Angular Components Created: 06 Jan 2026 Updated: 06 Jan 2026

Component Communication

In a modular Angular architecture, components must act as isolated units that communicate through well-defined APIs. This ensures that your UI remains maintainable and testable. We will cover the three pillars of communication: Inputs (Data Down), Outputs (Events Up)

Step 1: The Data Model

First, we define what a "Product" looks like.

src/app/models/product.model.ts

export interface Product {
id: number;
title: string;
price: number;
description: string;
}

Step 2: The Child Component (ProductDetail)

The child component is a "UI component." It doesn't fetch data; it simply displays whatever product the parent gives it.

A. The Logic (TypeScript)

We use input() to receive the product and output() to notify the parent when the user wants to add it to the cart.

src/app/product-detail/product-detail.component.ts

import { Component, input, output } from '@angular/core';
import { Product } from '../models/product.model';

@Component({
selector: 'app-product-detail',
standalone: true,
templateUrl: './product-detail.component.html'
})
export class ProductDetailComponent {
// Input: Parent pushes a Product here
product = input<Product>();

// Output: Child notifies Parent when button is clicked
addToCart = output<Product>();

onAdd() {
// We emit the current product back to the parent
if (this.product()) {
this.addToCart.emit(this.product()!);
}
}
}

B. The Template (HTML)

Since product is a Signal, we read it by calling it as a function: product().

src/app/product-detail/product-detail.component.html

@if (product()) {
<div class="detail-box">
<h2>{{ product()!.title }}</h2>
<p>{{ product()!.description }}</p>
<p>Price: <strong>{{ product()!.price | currency }}</strong></p>
<button (click)="onAdd()">Add to Shopping Cart</button>
</div>
} @else {
<p>Please select a product from the list to see the details.</p>
}

Step 3: The Parent Component (ProductList)

The parent component manages the list of products and knows which one is currently selected.

A. The Logic (TypeScript)

The parent imports the child component and defines a method to handle the event coming from the child.

src/app/product-list/product-list.component.ts


import { Component } from '@angular/core';
import { Product } from '../models/product.model';
import { ProductDetailComponent } from '../product-detail/product-detail.component';

@Component({
selector: 'app-product-list',
standalone: true,
imports: [ProductDetailComponent], // Registering the child
templateUrl: './product-list.component.html'
})
export class ProductListComponent {
selectedProduct: Product | undefined;

products: Product[] = [
{ id: 1, title: 'Mechanical Keyboard', price: 89, description: 'RGB Backlit' },
{ id: 2, title: 'Gaming Mouse', price: 45, description: '16000 DPI' }
];

onProductAdded(product: Product) {
alert(`${product.title} has been added to your cart!`);
}
}

B. The Template (HTML)

The parent "talks" to the child through the selector <app-product-detail>.

src/app/product-list/product-list.component.html


<div class="container">
<h1>Our Products</h1>
<div class="list">
@for (p of products; track p.id) {
<div class="item" (click)="selectedProduct = p">
{{ p.title }}
</div>
}
</div>

<hr />

<app-product-detail
[product]="selectedProduct"
(addToCart)="onProductAdded($event)">
</app-product-detail>
</div>

Key Concepts Summary

  1. input(): Creates a "hole" in the child component where the parent can plug in data.
  2. output(): Creates an "emitter" that sends signals (and data) up to the parent.
  3. $event: A reserved keyword in the parent's HTML that holds the data sent by the child via emit().
  4. Property Binding []: Always used for Inputs (Data flowing into the child).
  5. Event Binding (): Always used for Outputs (Events flowing out of the child).
Share this lesson: