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.