Seit Angular 17 hat sich die Art, mit der wir Logik in unseren Templates steuern, grundlegend geändert. Die altbekannten strukturellen Direktiven wie *ngIf, *ngFor und *ngSwitch bekommen Konkurrenz durch eine neue, den Standard definierende Control Flow Syntax: @if, @for und @switch. Aber warum ganze? Ist es nur syntactic Sugar oder steckt mehr dahinter? TLDR;: Es ist mehr!

In diesem Beitrag tauchen wir tief in die neue Syntax ein, vergleichen sie mit den alten Direktiven und beleuchten die Vorteile, die weit über die reine Optik hinausgehen.

Warum ein neuer Control Flow?

Das Angular-Team verfolgt mit dieser Änderung mehrere Ziele:

  • Bessere Performance: Die neue Syntax ist direkt in den Compiler integriert und benötigt keine Direktiven-Imports, was zu kleineren Bundles und potenziell schnellerer Ausführung führen kann (insbesondere in Kombination mit zukünftigen Zoneless-Strategien).
  • Verbesserte Developer Experience (DX): Eine intuitivere, klarere Syntax, die weniger fehleranfällig ist und schon beim visuellen Scannen des Codes ersichtlich ist.
  • Striktere Typisierung: Insbesondere @switch profitiert von besserer Type Narrowing.

Im Detail: @if, @else if, @else

Die neue Bedingungslogik ist sichtlich einfach:

@if (userLoggedIn()) {
  <p>Willkommen zurück, {{ userName() }}!</p>
  <button (click)="logout()">Logout</button>
} @else if (isLoading()) {
  <p>Lade Benutzerdaten...</p>
} @else {
  <p>Bitte einloggen.</p>
  <button (click)="login()">Login</button>
}

Im vergleich zu *ngIf:

  • Kein thenoder else mit Template-Referenzen mehr nötig - deutlich erhöhte Lesbarkeit.
  • Klar definierte Blöcke

Im Detail @for und @empty

Das Iterieren über Listen wurde ebenfalls angepasst, wie in folgendem Beispiel zu erkennen ist:

<ul>
  @for (user of users(); track user.id) {
    <li [class.first]="$first" [class.last]="$last" [class.even]="$event" [class.odd]="$odd">
      {{ i + 1 }}/{{ $count }}: {{ user.name }} (ID: {{ user.id }})
    </li>
  } @empty {
    <li>Keine Benutzer gefunden.</li>
  }
</ul>

Zu beachten bei @for:

  • track ist nun Pflicht: Das führt dazu, dass eine Funktion bzw. ein Parameter angegeben werden muss, anhand dessen das Tracking der Listeneinträge durch Angular geschieht. Dies verbessert die Performance des Renderings eklatant, da Angular erkennt, welches Element bei Änderungen neu gerendert werden muss, anstatt die ganze Liste neu darzustellen. Dies war vorher optional und wurde entsprechend oft vergessen ohne den Impact zu kennen.
  • empty-Block: Das Anzeigen von Empty-States wird hiermit out of the Box durch Angular unterstützt und spart mühsame IF-Abfragen.
  • Implizite Variablen: Variablen, die früher im Schleifen-Kopf expliziert definiert werden mussten, stehen nun direkt zu Verfügung. Diese sind $index, $first, $last, $even, $odd und $count.

Im Detail: @switch, @case und @default

Zustandsabhängige Darstellungen sind nun deutlich mehr straight-forward zu lösen.

Im vergleich zu *ngSwitch:

  • Bessere Typprüfung innerhalb der @case-Blöcke (Type Narrowing)
  • Klarere Syntax und deutlich getrenntere Blöcke ohne *ngSwitchCase-Directiven
@switch (accessLevel()) {
  @case ('admin') {
    <app-admin-dashboard />
  }
  @case ('moderator') {
    <app-moderator-tools />
  }
  @default {
    <app-user-profile />
  }
}

Vorteile zusammengefasst:

  • Performance: Potenziell kleinere Bundles und effizientere Change Detection (insbesondere in Zukunft). track bei @for ist ein direkter Performance-Gewinn.
  • Developer Experience: Intuitiver, weniger Boilerplate, besser lesbar.
  • Typsicherheit: Vor allem bei @switch verbessert.
  • Keine Imports: Die neue Syntax ist eingebaut, keine Notwendigkeit, CommonModule oder NgIf/NgFor etc. zu importieren (gerade bei Standalone Components, welche der neue Standard sind, sehr von Vorteil).

Migration

Die Migration ist, wie man es aus dem Angular-Ecosystem mittlerweile gewohnt ist, sehr einfach und Komfortabel durchzuführen. Das Angular Team bietet hierfür eine Schematic an, mit welcher existierender Code automatisch migriert und auf Wunsch auch formatiert wird:

ng generate @angular/core:control-flow

Fazit

Der neue Control Flow ab Angular Version 17 ist weit mehr als nur eine kosmetische Änderung. Er verbessert die Performance, die Developer Experience und die Typsicherheit. Die Pflicht zum track-Keyword bei @for allein ist ein riesiger Schritt für effizientere Listen-Updates. Es gibt keinen Grund, mit der alten Syntax zu arbeiten, wenn man mit Angular 17+ arbeitet!