Skip to content

Directives

A directive attaches behavior to a DOM element. Angular has three kinds: components (directives with a template), structural directives (change the DOM’s structure β€” add/remove elements, like *ngIf/*ngFor, or the modern built-in control flow @if/@for), and attribute directives (change an element’s appearance/behavior without adding/removing it, like ngClass/ngStyle).

@Component({
selector: 'app-list',
template: `
<!-- Modern built-in control flow (Angular 17+), recommended for new code -->
@if (items.length > 0) {
@for (item of items; track item.id) {
<p>{{ item.name }}</p>
}
} @else {
<p>No items</p>
}
<!-- Older structural directive syntax, still widely seen in existing codebases -->
<p *ngIf="items.length > 0">Has items</p>
<p *ngFor="let item of items; trackBy: trackById">{{ item.name }}</p>
<!-- Attribute directive -->
<div [ngClass]="{ active: isActive, disabled: !isEnabled }">Status</div>
`,
})
export class ListComponent {
items = [{ id: 1, name: 'Apple' }];
isActive = true;
isEnabled = true;
trackById(index: number, item: { id: number }) { return item.id; }
}

Using *ngFor without a track/trackBy on a list that changes over time β€” without it, Angular can’t tell which items are β€œthe same” between renders, so it may destroy and recreate DOM elements unnecessarily (losing input focus, animation state, etc.) instead of reusing them.

<!-- No tracking -- Angular may re-render every item on any change to the array -->
<div *ngFor="let item of items">{{ item.name }}</div>
<!-- Modern control flow requires track and forces you to think about it -->
@for (item of items; track item.id) {
<div>{{ item.name }}</div>
}
  1. What are the three kinds of Angular directives?

    AnswerComponents (directives with a template), structural directives (change DOM structure, like *ngIf/@if), and attribute directives (change appearance/behavior without adding/removing elements, like ngClass).
  2. What’s the modern, built-in alternative to *ngFor/*ngIf introduced in Angular 17?

    AnswerThe block-based control flow syntax β€” @for, @if, @switch β€” which requires no imports and mandates a track expression on @for.
  3. Why does skipping trackBy/track on a repeated list hurt performance?

    AnswerWithout it, Angular can't identify which items persisted between renders, so it may unnecessarily destroy and recreate DOM nodes for unchanged items instead of reusing them.