On this page
Components and Templates
Components control a portion of the screen. Each component has a TypeScript class, an HTML template, and optional styles.
Creating a Component
ng generate component user-card
This creates four files under src/app/user-card/:
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-user-card',
standalone: true,
templateUrl: './user-card.component.html',
styleUrl: './user-card.component.css'
})
export class UserCardComponent {
@Input() name = '';
@Input() email = '';
}
user-card.component.html:
<div class="card">
<h2>{{ name }}</h2>
<p>{{ email }}</p>
</div>
Use it in a parent template:
<app-user-card name="Alice" email="[email protected]"></app-user-card>
Inline Templates and Styles
For small components, keep everything in one file:
@Component({
selector: 'app-badge',
standalone: true,
template: `<span class="badge">{{ label }}</span>`,
styles: [`.badge { background: #007bff; color: white; padding: 2px 8px; }`]
})
export class BadgeComponent {
@Input() label = '';
}
Component Composition
Build complex UIs from smaller pieces:
@Component({
selector: 'app-user-list',
standalone: true,
imports: [UserCardComponent],
template: `
@for (user of users; track user.id) {
<app-user-card [name]="user.name" [email]="user.email" />
}
`
})
export class UserListComponent {
users = [
{ id: 1, name: 'Alice', email: '[email protected]' },
{ id: 2, name: 'Bob', email: '[email protected]' }
];
}
Input and Output
Pass data down with @Input(), emit events up with @Output():
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-counter',
standalone: true,
template: `
<p>Count: {{ count }}</p>
<button (click)="increment()">+1</button>
`
})
export class CounterComponent {
@Input() count = 0;
@Output() countChange = new EventEmitter<number>();
increment() {
this.countChange.emit(this.count + 1);
}
}
Parent usage:
<app-counter [count]="total" (countChange)="total = $event" />
Lifecycle Hooks
Run code at specific moments in a component’s life:
import { Component, OnInit, OnDestroy } from '@angular/core';
@Component({
selector: 'app-timer',
standalone: true,
template: `<p>Seconds: {{ seconds }}</p>`
})
export class TimerComponent implements OnInit, OnDestroy {
seconds = 0;
private intervalId?: ReturnType<typeof setInterval>;
ngOnInit() {
this.intervalId = setInterval(() => this.seconds++, 1000);
}
ngOnDestroy() {
clearInterval(this.intervalId);
}
}
| Hook | When it runs |
|---|---|
ngOnInit |
After first @Input() values are set |
ngOnChanges |
When an @Input() value changes |
ngOnDestroy |
Just before the component is removed |
Keep components focused: one responsibility, clear inputs and outputs, and templates that are easy to read.