Component
Understand how Angular components combine TypeScript logic, HTML templates, styles, inputs, outputs, and lifecycle behavior into reusable UI building blocks.
Lesson content
What is an Angular Component? A component is the main building block of an Angular application. Each component controls a specific part of the user interface. Simple Definition A component combines: TypeScript logic HTML template CSS styles Angular metadata Component Formula Component = TypeScript Class + Template + Styles + Metadata Basic Component Example import { Component } from '@angular/core'; @Component({ selector: 'app-user-card', standalone: true, template: ` <section class="card"> <h2>{{ userName }}</h2> <button (click)="showMessage()"> Show Message </button> </section> `, styles: ` .card { padding: 16px; border: 1px solid #ccc; } ` }) export class UserCardComponent { userName = 'Ajay'; showMessage() { console.log( 'Button clicked' ); } } Main Parts of a Component Part Purpose TypeScript class Contains data and behavior Template Defines the user interface Styles Controls the component appearance @Component() Adds Angular metadata Selector Defines how the component is used in HTML Imports Lists template dependencies @Component Decorator The @Component() decorator tells Angular that a TypeScript class is a component. @Component({ selector: 'app-product', standalone: true, template: ` <h2>Product</h2> ` }) export class ProductComponent {} Component Metadata selector The selector defines the custom HTML element used to render the component. selector: 'app-product-card' Usage <app-product-card></app-product-card> standalone A standalone component can directly import the components, directives, and pipes used in its template. standalone: true template The template property defines inline HTML. template: ` <h2>Dashboard</h2> ` templateUrl Use templateUrl when the template is stored in a separate file. templateUrl: './user-card.component.html' styles The styles property defines inline component styles. styles: ` h2 { font-weight: bold; } ` styleUrl Use styleUrl when styles are stored in a separate file. styleUrl: './user-card.component.css' imports The imports property makes standalone template dependencies available. imports: [ RouterLink, AsyncPipe, UserCardComponent ] Inline vs External Files Inline External Small components Large components Template inside TypeScript Separate HTML file Styles inside TypeScript Separate CSS file Quick to read in one place Easier to organize complex views Using a Child Component Child Component @Component({ selector: 'app-user-card', standalone: true, template: ` <h3>User Card</h3> ` }) export class UserCardComponent {} Parent Component import { Component } from '@angular/core'; @Component({ selector: 'app-dashboard', standalone: true, imports: [ UserCardComponent ], template: ` <h2>Dashboard</h2> <app-user-card /> ` }) export class DashboardComponent {} Component Composition Flow App Component ↓ Dashboard Component ↓ User Card Component ↓ Reusable UI Component Data Binding Interpolation userName = 'Ajay'; <h2>{{ userName }}</h2> Property Binding isDisabled = true; <button [disabled]="isDisabled" > Save </button> Event Binding saveUser() { console.log('User saved'); } <button (click)="saveUser()" > Save </button> Component Inputs Inputs allow a parent component to pass data to a child component. Child Component import { Component, input } from '@angular/core'; @Component({ selector: 'app-user-card', standalone: true, template: ` <h2>{{ name() }}</h2> ` }) export class UserCardComponent { name = input.required<string>(); } Parent Template <app-user-card [name]="userName" /> Input Flow Parent Data ↓ Input Binding ↓ Child Component ↓ Child Template Component Outputs Outputs allow a child component to send events to a parent component. Child Component import { Component, output } from '@angular/core'; @Component({ selector: 'app-save-button', standalone: true, template: ` <button (click)="save()" > Save </button> ` }) export class SaveButtonComponent { saved = output<string>(); save() { this.saved.emit( 'User saved' ); } } Parent Template <app-save-button (saved)="handleSaved($event)" /> Output Flow Child Action ↓ output().emit() ↓ Parent Event Handler ↓ Parent State Updates Two-Way Component Binding The model() API can create a writable component input that supports two-way binding. Child Component import { Component, model } from '@angular/core'; @Component({ selector: 'app-name-editor', standalone: true, template: ` <input [value]="value()" (input)="updateValue($event)" /> ` }) export class NameEditorComponent { value = model(''); updateValue(event: Event) { const input = event.target as HTMLInputElement; this.value.set( input.value ); } } Parent Template <app-name-editor [(value)]="userName" /> Component State with Signals import { Component, computed, signal } from '@angular/core'; @Component({ selector: 'app-counter', standalone: true, template: ` <p> Count: {{ count() }} </p> <p> Double: {{ doubleCount() }} </p> <button (click)="increment()" > Increment </button> ` }) export class CounterComponent { count = signal(0); doubleCount = computed( () => this.count() * 2 ); increment() { this.count.update( value => value + 1 ); } } Component Lifecycle Angular creates, initializes, checks, renders, and destroys component instances. Component Created ↓ Inputs Initialized ↓ ngOnInit() ↓ View Rendered ↓ Changes Checked ↓ ngOnDestroy() Lifecycle Example import { Component, OnDestroy, OnInit } from '@angular/core'; @Component({ selector: 'app-clock', standalone: true, template: ` <p>Clock</p> ` }) export class ClockComponent implements OnInit, OnDestroy { private timer?: number; ngOnInit() { this.timer = window.setInterval( () => console.log('Tick'), 1000 ); } ngOnDestroy() { window.clearInterval( this.timer ); } } Host Element Every component is attached to a host element that matches its selector. <app-user-card> Component view renders here </app-user-card> Host Bindings and Listeners The host metadata property can bind classes, attributes, properties, and events on the component host element. @Component({ selector: 'app-status', standalone: true, host: { '[class.active]': 'isActive', '[attr.aria-label]': 'label', '(click)': 'toggle()' }, template: ` <span>Status</span> ` }) export class StatusComponent { isActive = false; label = 'Toggle status'; toggle() { this.isActive = !this.isActive; } } View Encapsulation View encapsulation controls how component styles are scoped. Mode Behavior Emulated Scopes styles using generated attributes ShadowDom Uses the browser Shadow DOM None Makes component styles global Example import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: 'app-card', standalone: true, encapsulation: ViewEncapsulation.Emulated, template: ` <p>Card</p> `, styles: ` p { font-weight: bold; } ` }) export class CardComponent {} Change Detection Strategy A component can use OnPush change detection to reduce unnecessary checks. import { ChangeDetectionStrategy, Component, signal } from '@angular/core'; @Component({ selector: 'app-counter', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: ` <p>{{ count() }}</p> ` }) export class CounterComponent { count = signal(0); } Signals work naturally with OnPush because Angular tracks where signals are read. Smart and Presentational Components Smart Component Presentational Component Loads data Displays data Uses services Uses inputs and outputs Manages feature state Focuses on reusable UI Coordinates child components Emits user actions Dynamic Components Angular can create components dynamically when the component type is not known directly in the template. import { Component, ViewContainerRef, inject } from '@angular/core'; @Component({ selector: 'app-host', standalone: true, template: ` <button (click)="loadComponent()" > Load </button> ` }) export class HostComponent { private viewContainer = inject(ViewContainerRef); async loadComponent() { const module = await import( './alert.component' ); this.viewContainer .createComponent( module.AlertComponent ); } } Component Tree Angular applications form a tree of component instances. AppComponent │ ├── HeaderComponent │ ├── DashboardComponent │ ├── SummaryComponent │ └── UserListComponent │ └── FooterComponent Data usually flows downward through inputs, while events flow upward through outputs. Parent Data ↓ Child Input Child Event ↑ Parent Output Handler Component vs Directive Component Directive Has its own template Usually has no template Creates a UI block Enhances existing elements Uses @Component() Uses @Directive() Normally uses an element selector Normally uses an attribute selector Common Mistakes 1. Putting API Logic Directly in Components Avoid: export class UserComponent { loadUsers() { fetch('/api/users'); } } Prefer a dedicated service for data access. 2. Creating Very Large Components Split large components into smaller feature-focused components. 3. Forgetting Standalone Imports A standalone component must import the directives, pipes, and child components used by its template. 4. Mutating Input Data Avoid directly mutating objects received from a parent. 5. Using Methods for Expensive Template Calculations Prefer computed() , pipes, or pre-calculated values for expensive derived data. 6. Subscribing Without Cleanup Use the async pipe, takeUntilDestroyed() , or another managed cleanup mechanism for long-running subscriptions. Best Practices Keep each component focused on one UI responsibility Use services for reusable business logic and API communication Use standalone components for modern application structure Use inputs for data and outputs for events Prefer signals for local reactive component state Use OnPush where it improves predictable performance Keep templates simple and readable Split large components into smaller reusable components Use semantic and accessible HTML Test component behavior independently Interview Questions What is an Angular component? An Angular component is a reusable UI building block that combines a TypeScript class, template, styles, and component metadata. What does the @Component decorator do? It provides metadata that tells Angular how to create, render, configure, and use the component. What is a standalone component? A standalone component directly declares its template dependencies through the imports property and does not require declaration in an NgModule. What is a component selector? A selector is the HTML pattern Angular uses to identify where a component should be created. What is the difference between a component and a directive? A component has its own template and creates a section of UI. A directive changes the behavior or appearance of an existing element. How does data flow between components? Parent components normally pass data through inputs, while child components send events through outputs. What is view encapsulation? View encapsulation controls whether component styles are scoped, use Shadow DOM, or become global. What is OnPush change detection? OnPush reduces unnecessary component checks by updating the component for specific triggers such as input changes, events, observable emissions used by the template, and signal changes. Key Point A component owns a reusable section of UI and connects data, behavior, templates, styles, and user interaction. Easy Formula Component = Class + Template + Styles + Metadata Input = Parent to Child Data Output = Child to Parent Event Signal = Reactive Component State Service = Shared Logic Selector = Component HTML Name Component Created ↓ Inputs Received ↓ Template Rendered ↓ User Interacts ↓ Component State Changes ↓ UI Updates ↓ Component Destroyed