Skip to content

Components Basics 🧩

Components are the building blocks of Angular applications. Each component controls a part of the screen and combines HTML template, TypeScript logic, and CSS styles.

A component consists of:

  • Template (HTML) - What the user sees
  • Class (TypeScript) - Logic and data
  • Styles (CSS) - How it looks
  • Metadata (Decorator) - Configuration
@Component({
selector: 'app-user-card',
template: `<h2>{{user.name}}</h2>`,
styles: [`h2 { color: blue; }`]
})
export class UserCard {
user = { name: 'John Doe' };
}
Terminal window
# Generate a new component
ng generate component user-profile
# Short form
ng g c user-profile
# Generate in specific folder
ng g c components/user-profile

Create three files:

user-profile.ts

import { Component } from '@angular/core';
@Component({
selector: 'app-user-profile',
templateUrl: './user-profile.html',
styleUrls: ['./user-profile.css']
})
export class UserProfile {
userName = 'Jane Smith';
userEmail = 'jane@example.com';
showProfile() {
alert(`User: ${this.userName}`);
}
}

user-profile.html

<div class="profile-card">
<h2>{{userName}}</h2>
<p>{{userEmail}}</p>
<button (click)="showProfile()">Show Profile</button>
</div>

user-profile.css

.profile-card {
border: 1px solid #ddd;
padding: 20px;
border-radius: 8px;
max-width: 300px;
}
h2 {
color: #333;
margin-top: 0;
}
button {
background: #007bff;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
@Component({
selector: 'app-example', // How to use: <app-example>
templateUrl: './example.html', // External template
template: `<h1>Inline template</h1>`, // Inline template
styleUrls: ['./example.css'], // External styles
styles: [`h1 { color: red; }`], // Inline styles
imports: [CommonModule, FormsModule] // Required imports
})
export class Product {
// Properties
productName = 'iPhone 15';
price = 999;
inStock = true;
tags = ['electronics', 'mobile', 'apple'];
// Computed property (getter)
get formattedPrice(): string {
return `$${this.price.toFixed(2)}`;
}
// Methods
addToCart(): void {
console.log(`Added ${this.productName} to cart`);
}
toggleStock(): void {
this.inStock = !this.inStock;
}
// Private method
private calculateDiscount(): number {
return this.price * 0.1;
}
}
<!-- Using the component -->
<app-user-profile></app-user-profile>
<!-- Multiple instances -->
<div class="users">
<app-user-profile></app-user-profile>
<app-user-profile></app-user-profile>
</div>
// Element selector (most common)
selector: 'app-header'
// Usage: <app-header></app-header>
// Attribute selector
selector: '[app-highlight]'
// Usage: <div app-highlight></div>
// Class selector
selector: '.app-widget'
// Usage: <div class="app-widget"></div>

Components have lifecycle hooks that let you tap into key moments:

import { Component, OnInit, OnDestroy } from '@angular/core';
export class MyComponent implements OnInit, OnDestroy {
ngOnInit(): void {
// Called after component initialization
console.log('Component initialized');
}
ngOnDestroy(): void {
// Called before component is destroyed
console.log('Component destroyed');
}
}
  • ngOnInit - Component initialized
  • ngOnChanges - Input properties changed
  • ngOnDestroy - Component about to be destroyed
  • ngAfterViewInit - View fully initialized
import { Component, input } from '@angular/core';
// Child component
export class ChildComponent {
message = input('');
count = input(0);
}
<!-- Parent template -->
<app-child [message]="parentMessage" [count]="5"></app-child>
import { Component, output } from '@angular/core';
// Child component
export class ChildComponent {
notify = output<string>();
sendMessage(): void {
this.notify.emit('Hello from child!');
}
}
<!-- Parent template -->
<app-child (notify)="handleMessage($event)"></app-child>
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { FormsModule } from '@angular/forms';
@Component({
selector: 'app-counter',
imports: [CommonModule, FormsModule],
template: `
<div>
<h3>Counter: {{count}}</h3>
<button (click)="increment()">+</button>
<button (click)="decrement()">-</button>
</div>
`
})
export class Counter {
count = 0;
increment(): void {
this.count++;
}
decrement(): void {
this.count--;
}
}

Let’s build a reusable product card component:

import { Component, input, output } from '@angular/core';
import { CommonModule } from '@angular/common';
interface Product {
id: number;
name: string;
price: number;
image: string;
inStock: boolean;
}
@Component({
selector: 'app-product-card',
imports: [CommonModule],
template: `
<div class="product-card" [class.out-of-stock]="!product().inStock">
<img [src]="product().image" [alt]="product().name">
<div class="product-info">
<h3>{{product().name}}</h3>
<p class="price">\${{product().price}}</p>
@if (!product().inStock) {
<p class="stock">Out of Stock</p>
}
<button
(click)="onAddToCart()"
[disabled]="!product().inStock"
class="add-btn">
Add to Cart
</button>
</div>
</div>
`,
})
export class ProductCard {
product = input.required<Product>();
addToCart = output<Product>();
onAddToCart(): void {
if (this.product().inStock) {
this.addToCart.emit(this.product());
}
}
}

Usage:

<app-product-card
[product]="selectedProduct"
(addToCart)="handleAddToCart($event)">
</app-product-card>

Each component should have one clear purpose.

Keep components small and focused on their specific task.

Design components to be reusable across different parts of your app.

Use descriptive names that indicate the component’s purpose.

Always validate inputs and provide defaults.

import { Component, input, computed } from '@angular/core';
export class MyComponent {
private rawCount = input(0);
// Use computed() for validated/transformed input values
count = computed(() => {
const value = this.rawCount();
return value >= 0 ? value : 0;
});
}
  • Understand component structure (template, class, styles, metadata)
  • Know how to create components with CLI
  • Use input() for parent-to-child communication
  • Use output() for child-to-parent communication
  • Implement lifecycle hooks when needed
  • Create reusable, focused components
  • Use standalone components for modern Angular
  1. Templates & Data Binding - Master template syntax
  2. Directives - Learn built-in and custom directives
  3. Services & DI - Share data between components

Remember: Components are the heart of Angular applications. Master them, and you’ll build better, more maintainable apps! 🎯