Directives
A directive changes what an element does or how many times it appears, without you writing any imperative DOM code — the two you'll reach for constantly are *ngIf and *ngFor.
*ngIf: conditionally rendering an element
TS status.component.ts
export class StatusComponent {
isLoggedIn = false;
}
HTML status.component.html
<p *ngIf="isLoggedIn">Welcome back!</p> <p *ngIf="!isLoggedIn">Please log in.</p>
Rendered output
<p>Please log in.</p>
Unlike a CSS display: none toggle, an element with a false *ngIf condition is removed from the DOM entirely, not just hidden — Angular adds it back only when the condition becomes true again.
*ngFor: repeating an element per item
TS todo-list.component.ts
export class TodoListComponent {
todos = ['Buy milk', 'Walk the dog', 'Write lesson'];
}
HTML todo-list.component.html
<ul>
<li *ngFor="let todo of todos">{{ todo }}</li>
</ul>
Rendered output
<ul> <li>Buy milk</li> <li>Walk the dog</li> <li>Write lesson</li> </ul>
*ngFor="let todo of todos" reads almost like English: for each item in todos, call it todo, and render the <li> once per item using that name.
Getting the index inside *ngFor
HTML todo-list.component.html
<li *ngFor="let todo of todos; let i = index">
{{ i + 1 }}. {{ todo }}
</li>
Rendered output
1. Buy milk 2. Walk the dog 3. Write lesson
let i = index exposes the zero-based position of each item as i, which is why the display adds 1 to make it a human-friendly 1-based count.
Note: for large or frequently-changing lists, add a
trackBy function to *ngFor. Without one, Angular's default change detection compares list items by identity and can end up destroying and recreating far more DOM elements than actually changed — trackBy tells Angular how to recognize "this is still the same item" (usually by an id), which keeps re-renders fast and avoids losing things like input focus or CSS transition state on unrelated rows.