Angular Control Flow Syntax in 2026: @if, @for, @switch en Interviewvragen
Uitgebreide gids over de nieuwe Angular Control Flow Syntax met @if, @for en @switch. Performance-optimalisaties, Signal-integratie en veelgestelde interviewvragen voor Angular-ontwikkelaars.

De Control Flow Syntax van Angular (@if, @for, @switch) vervangt de structurele directives *ngIf, *ngFor en *ngSwitch die jarenlang Angular-templates domineerden. Geïntroduceerd in Angular 17, stabiel sinds Angular 18 en standaard in Angular 22, brengt deze block-gebaseerde syntax templates dichter bij standaard programmeerconstructies en maakt betere performance-optimalisaties mogelijk.
Voer ng generate @angular/core:control-flow uit om bestaande templates automatisch te migreren van structurele directives naar de nieuwe Control Flow Syntax. Beide syntaxen bestaan naast elkaar tijdens de migratie, maar ngIf, ngFor en ngSwitch zijn soft-deprecated sinds Angular 19.
Waarom Angular Structurele Directives Verving door Block-Syntax
Structurele directives vereisten het importeren van CommonModule, gebruikten microsyntax die verschilde van JavaScript, en dwongen ontwikkelaars om content in ng-template te wrappen voor complexe condities. De nieuwe Control Flow Syntax lost deze problemen op:
- Geen imports nodig:
@if,@foren@switchzijn ingebouwd in het framework - JavaScript-achtige syntax: condities en loops lezen als standaardcode
- Native
@else-ondersteuning: geenng-template-referenties meer nodig voor else-takken - Betere tree-shaking: ongebruikte Control Flow Blocks hebben geen impact op de bundlegrootte
De Angular-documentatie raadt aan om block-syntax volledig te adopteren in alle nieuwe projecten en bestaande codebases incrementeel te migreren.
@if: Conditionele Rendering zonder ng-template
Het @if-block rendert conditioneel content gebaseerd op een truthy expressie. In tegenstelling tot *ngIf ondersteunt het direct @else if en @else-takken:
import { Component, input } from '@angular/core';
@Component({
selector: 'app-user-status',
template: `
@if (user().role === 'admin') {
<app-admin-panel />
} @else if (user().role === 'editor') {
<app-editor-panel />
} @else {
<app-viewer-panel />
}
`
})
export class UserStatusComponent {
user = input.required<{ role: string }>();
}Het @if-block ondersteunt ook variabele-aliasing met het as-keyword, dat waarden extraheert uit geneste expressies:
<!-- Vermijdt herhaalde property-toegang -->
@if (user().profile?.settings?.theme; as theme) {
<p>Huidig thema: {{ theme }}</p>
}Dit patroon is bijzonder nuttig bij het werken met async data of diep geneste objecten, aangezien de gealiaste variabele alleen gedefinieerd is wanneer de conditie truthy is.
@for: Iteratie met Verplichte Track-Expressie
Het @for-block itereert over elk JavaScript-iterable, met optimalisaties voor arrays. In tegenstelling tot *ngFor vereist het een track-expressie:
import { Component, input } from '@angular/core';
interface Product {
id: string;
name: string;
price: number;
}
@Component({
selector: 'app-product-list',
template: `
@for (product of products(); track product.id) {
<app-product-card [product]="product" />
} @empty {
<p>Geen producten beschikbaar</p>
}
`
})
export class ProductListComponent {
products = input.required<Product[]>();
}De track-expressie vertelt Angular hoe elk item te identificeren over re-renders heen. Het kiezen van de juiste tracking-property heeft directe impact op de performance:
| Track-Expressie | Toepassing | Performance-Impact |
|---|---|---|
track item.id | Items met unieke identifiers | Optimaal: minimale DOM-updates |
track $index | Statische lijsten die nooit worden gesorteerd | Acceptabel: volledige re-render bij herschikking |
track item | Referentie-tracking | Slecht: nieuwe referentie = nieuwe DOM-node |
Contextvariabelen in @for-Blocks
Angular biedt impliciete variabelen binnen @for-blocks die iteratie-metadata exponeren:
@for (item of items(); track item.id; let i = $index, isLast = $last) {
<li class="item" [class.last]="isLast">
{{ i + 1 }}. {{ item.name }}
</li>
}Beschikbare contextvariabelen:
$index: nulgebaseerde positie$count: totaal aantal items$first,$last: boolean flags voor eerste/laatste items$even,$odd: boolean flags gebaseerd op index-pariteit
Klaar om je Angular gesprekken te halen?
Oefen met onze interactieve simulatoren, flashcards en technische tests.
@switch: Type-Safe Conditionele Vertakking
Het @switch-block biedt exhaustieve pattern matching met strikte gelijkheid (===) vergelijking:
import { Component, input } from '@angular/core';
type OrderStatus = 'pending' | 'processing' | 'shipped' | 'delivered';
@Component({
selector: 'app-status-badge',
template: `
@switch (status()) {
@case ('pending') {
<span class="badge badge-gray">In Afwachting</span>
}
@case ('processing') {
<span class="badge badge-blue">In Verwerking</span>
}
@case ('shipped') {
<span class="badge badge-yellow">Verzonden</span>
}
@case ('delivered') {
<span class="badge badge-green">Afgeleverd</span>
}
}
`
})
export class StatusBadgeComponent {
status = input.required<OrderStatus>();
}In tegenstelling tot JavaScript's switch heeft Angular's @switch geen fallthrough-gedrag. Meerdere condities die op hetzelfde block gericht zijn vereisen opeenvolgende @case-statements:
@switch (userRole()) {
@case ('admin')
@case ('superadmin') {
<app-admin-dashboard />
}
@case ('editor')
@case ('reviewer') {
<app-editor-dashboard />
}
@default {
<app-viewer-dashboard />
}
}Exhaustieve Type-Controle met @default never
Angular 22 ondersteunt compile-time exhaustiveness checking. Het gebruik van @default never; declareert dat er geen resterende cases zouden moeten bestaan:
type Theme = 'light' | 'dark' | 'system';
// Compilatiefout als een Theme-waarde ontbreekt in @case-blocks
@switch (theme()) {
@case ('light') { /* ... */ }
@case ('dark') { /* ... */ }
@case ('system') { /* ... */ }
@default never;
}Het toevoegen van een nieuwe waarde aan de Theme-union veroorzaakt een compilatiefout, wat ontwikkelaars dwingt alle cases af te handelen.
Control Flow Syntax en Angular Signals Integratie
Control Flow Blocks integreren naadloos met Angular Signals, waardoor fijnkorrelige reactiviteit mogelijk wordt:
import { Component, computed, signal } from '@angular/core';
@Component({
selector: 'app-dashboard',
template: `
@if (isLoading()) {
<app-skeleton />
} @else if (hasError()) {
<app-error [message]="errorMessage()" />
} @else {
@for (item of filteredItems(); track item.id) {
<app-item-card [item]="item" />
} @empty {
<p>Geen items komen overeen met de filters</p>
}
}
`
})
export class DashboardComponent {
items = signal<Item[]>([]);
filter = signal('');
isLoading = signal(true);
hasError = signal(false);
errorMessage = signal('');
// Computed signal wordt alleen opnieuw berekend wanneer dependencies veranderen
filteredItems = computed(() =>
this.items().filter(item =>
item.name.toLowerCase().includes(this.filter().toLowerCase())
)
);
}Wanneer een signal wordt bijgewerkt, herevalueert Angular alleen de betreffende Control Flow Blocks. Gecombineerd met Angular's zoneless change detection maakt dit hooggeoptimaliseerde rendering mogelijk.
Veelgestelde Interviewvragen over Angular Control Flow
Technische interviews testen vaak het begrip van Control Flow Syntax, vooral de verschillen met structurele directives.
Vraag 1: Waarom is track verplicht in @for?
De track-expressie geeft Angular een stabiele identiteit voor elk item. Zonder deze kan Angular niet efficiënt bepalen welke DOM-nodes moeten worden aangemaakt, bijgewerkt of verwijderd wanneer de collectie verandert. Het verplicht maken van track dwingt ontwikkelaars om een expliciete beslissing over identiteit te nemen, waardoor de performance-valkuilen van impliciete referentie-tracking worden vermeden.
Vraag 2: Hoe verschilt @if van *ngIf met async pipe?
Beide kunnen observables verwerken, maar @if met signals biedt synchrone toegang tot waarden:
// Met *ngIf en async pipe (legacy)
<div *ngIf="user$ | async as user">{{ user.name }}</div>
// Met @if en signals (modern)
@if (user(); as user) {
<div>{{ user.name }}</div>
}De signal-aanpak vermijdt subscription-beheer en integreert beter met Angular's change detection.
Vraag 3: Kan @switch complexe @if/@else if-ketens vervangen?
@switch moet worden gebruikt bij het vergelijken van een enkele expressie met meerdere discrete waarden. Voor complexe boolean-condities die verschillende expressies bevatten, blijft @if/@else if geschikter:
<!-- Gebruik @switch voor enkele expressie, meerdere waarden -->
@switch (status()) {
@case ('active') { ... }
@case ('inactive') { ... }
}
<!-- Gebruik @if voor meerdere expressies -->
@if (isAdmin() && hasPermission('write')) {
...
} @else if (isEditor()) {
...
}Vraag 4: Wat gebeurt er met @for wanneer de collectie leeg is?
Wanneer de iterable geen items bevat, slaat Angular de @for-content volledig over. Het optionele @empty-block rendert fallback-content in dit geval. Zonder @empty wordt er niets gerenderd, wat verschilt van sommige frameworks die een lege container renderen.
Migreren van Structurele Directives naar Control Flow
De Angular CLI biedt een geautomatiseerde migratie-schematic:
# Migreer het hele project
ng generate @angular/core:control-flow
# Migreer een specifieke directory
ng generate @angular/core:control-flow --path=src/app/featuresDe schematic handelt de meeste transformaties automatisch af, maar controleer de output op edge cases:
| Structurele Directive | Control Flow Equivalent |
|---|---|
*ngIf="condition" | @if (condition) { } |
*ngIf="condition; else elseBlock" | @if (condition) { } @else { } |
*ngFor="let item of items" | @for (item of items; track item) { } |
*ngFor="let item of items; index as i" | @for (item of items; track item; let i = $index) { } |
[ngSwitch] + *ngSwitchCase | @switch + @case |
Na de migratie, verwijder CommonModule-imports uit standalone components die geen structurele directives meer gebruiken.
Begin met oefenen!
Test je kennis met onze gespreksimulatoren en technische tests.
Belangrijke Inzichten over Angular Control Flow Syntax
- Angular's Control Flow Syntax (
@if,@for,@switch) is de aanbevolen aanpak sinds Angular 19, ter vervanging van structurele directives - De
track-expressie in@foris verplicht: gebruik unieke identifiers zoalsitem.idvoor optimale performance, vermijdtrack itemdat referentie-gebaseerde re-renders veroorzaakt @ifondersteunt native@else ifen@else-takken zonderng-template, en hetas-keyword maakt aliassen voor truthy waarden voor hergebruik@switchgebruikt strikte gelijkheid en heeft geen fallthrough: opeenvolgende@case-statements richten zich op hetzelfde block, en@default never;maakt exhaustieve type-controle mogelijk- Control Flow Blocks integreren met Signals voor fijnkorrelige reactiviteit: alleen betreffende blocks worden opnieuw gerenderd wanneer signals worden bijgewerkt
- Voer
ng generate @angular/core:control-flowuit om bestaande templates automatisch te migreren
Zie jij de bug in Angular?
Een echt codefragment, een verborgen bug, één poging per dag. Zonder account uit te proberen.

Geschreven door
Anthony Fillion-MailletOprichter van SharpSkill
Al meer dan 10 jaar fullstack-ontwikkelaar. Hij leidt SharpSkill en staat in voor alles wat hier verschijnt.
Bijgewerkt op 3 september 2026
Tags
Delen
Gerelateerde artikelen

Angular 20 in 2026: Resource API, httpResource en sollicitatievragen
Angular 20 introduceert de Resource API en httpResource als signal-gebaseerde alternatieven voor handmatige HttpClient-subscriptions. Deze handleiding behandelt alle drie Resource-varianten, Zod-validatie en veelgestelde sollicitatievragen.

RxJS in Angular 2026: operators, Subjects en Signals-interop
RxJS in Angular 2026: de operators, Subjects en Signals-interop-patronen die Angular-ontwikkelaars in productie gebruiken, plus de meest voorkomende sollicitatievragen.

Angular Signals en Computed in 2026: Fijnkorrelige Reactiviteit en Sollicitatievragen
Een diepgaande gids over Angular Signals, Computed Signals en het reactieve model in Angular 20+. Bevat best practices, RxJS-interoperabiliteit en veelgestelde technische sollicitatievragen.