Składnia Control Flow w Angular 2026: @if, @for, @switch i pytania rekrutacyjne
Kompletny przewodnik po blokowej składni przepływu sterowania w Angular. Poznaj @if, @for, @switch z praktycznymi przykładami kodu i przygotuj się do rozmów kwalifikacyjnych.

Składnia control flow w Angular (@if, @for, @switch) zastępuje dyrektywy strukturalne *ngIf, *ngFor i *ngSwitch, które przez lata dominowały w szablonach Angular. Wprowadzona w Angular 17, stabilna od Angular 18 i domyślna od Angular 22, ta blokowa składnia przybliża szablony do standardowych konstrukcji programistycznych, jednocześnie umożliwiając lepsze optymalizacje wydajności.
Uruchom ng generate @angular/core:control-flow aby automatycznie zmigrować istniejące szablony z dyrektyw strukturalnych do nowej składni control flow. Obie składnie mogą współistnieć podczas migracji, ale ngIf, ngFor i ngSwitch są miękko zdeprecjonowane od Angular 19.
Dlaczego Angular zastąpił dyrektywy strukturalne składnią blokową
Dyrektywy strukturalne wymagały importowania CommonModule, używały mikro-składni różniącej się od JavaScript i zmuszały programistów do opakowywania treści w ng-template dla złożonych warunków. Nowa składnia control flow rozwiązuje te problemy:
- Brak wymaganych importów:
@if,@fori@switchsą wbudowane we framework - Składnia przypominająca JavaScript: warunki i pętle czytają się jak standardowy kod
- Natywne wsparcie dla
@else: koniec z referencjami dong-templatedla gałęzi else - Lepszy tree-shaking: nieużywane bloki control flow mają zerowy wpływ na bundle
Dokumentacja Angular zaleca pełne przyjęcie składni blokowej we wszystkich nowych projektach i stopniową migrację istniejących baz kodu.
@if: Renderowanie warunkowe bez ng-template
Blok @if warunkowo renderuje treść na podstawie wyrażenia prawdziwego. W przeciwieństwie do *ngIf, wspiera bezpośrednio gałęzie @else if i @else:
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 }>();
}Blok @if wspiera również aliasowanie zmiennych za pomocą słowa kluczowego as, które wyodrębnia wartości z zagnieżdżonych wyrażeń:
<!-- Unika wielokrotnego dostępu do właściwości -->
@if (user().profile?.settings?.theme; as theme) {
<p>Aktualny motyw: {{ theme }}</p>
}Ten wzorzec jest szczególnie przydatny podczas pracy z danymi asynchronicznymi lub głęboko zagnieżdżonymi obiektami, ponieważ aliasowana zmienna jest definiowana tylko gdy warunek jest prawdziwy.
@for: Iteracja z obowiązkowym wyrażeniem track
Blok @for iteruje po dowolnym iterowalnym obiekcie JavaScript, z optymalizacjami dla tablic. W przeciwieństwie do *ngFor, wymaga wyrażenia track:
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) {
<div class="product-card">
<h3>{{ product.name }}</h3>
<p>{{ product.price | currency }}</p>
</div>
} @empty {
<p>Brak dostępnych produktów</p>
}
`
})
export class ProductListComponent {
products = input.required<Product[]>();
}Wyrażenie track jest obowiązkowe, ponieważ umożliwia algorytmowi różnicowania Angular identyfikację elementów między cyklami detekcji zmian. Dzięki temu framework wie, które elementy DOM należy ponownie użyć, a które utworzyć od nowa.
Dostęp do zmiennych kontekstowych w @for
Blok @for udostępnia kilka zmiennych kontekstowych:
@for (item of items(); track item.id; let idx = $index, first = $first, last = $last) {
<div [class.first-item]="first" [class.last-item]="last">
{{ idx + 1 }}. {{ item.name }}
</div>
}Dostępne zmienne kontekstowe to:
$index- bieżący indeks (od 0)$first- czy to pierwszy element$last- czy to ostatni element$even- czy indeks jest parzysty$odd- czy indeks jest nieparzysty$count- całkowita liczba elementów w kolekcji
@switch: Rozgałęzienia wielokrotne bez ng-container
Blok @switch obsługuje scenariusze z wieloma warunkami bez potrzeby zagnieżdżania elementów ng-container:
import { Component, input } from '@angular/core';
type NotificationType = 'success' | 'warning' | 'error' | 'info';
@Component({
selector: 'app-notification',
template: `
@switch (type()) {
@case ('success') {
<div class="alert alert-success">
<span class="icon-check"></span>
<ng-content />
</div>
}
@case ('warning') {
<div class="alert alert-warning">
<span class="icon-warning"></span>
<ng-content />
</div>
}
@case ('error') {
<div class="alert alert-error">
<span class="icon-error"></span>
<ng-content />
</div>
}
@default {
<div class="alert alert-info">
<span class="icon-info"></span>
<ng-content />
</div>
}
}
`
})
export class NotificationComponent {
type = input<NotificationType>('info');
}Blok @switch używa ścisłego porównania (===), co eliminuje nieoczekiwane zachowanie związane z koercją typów.
Zagnieżdżanie bloków control flow
Bloki control flow można swobodnie zagnieżdżać, tworząc złożoną logikę renderowania:
@if (isLoading()) {
<app-skeleton-loader />
} @else {
@for (category of categories(); track category.id) {
<section class="category">
<h2>{{ category.name }}</h2>
@for (product of category.products; track product.id) {
@switch (product.availability) {
@case ('in_stock') {
<app-product-card [product]="product" />
}
@case ('pre_order') {
<app-preorder-card [product]="product" />
}
@default {
<app-out-of-stock-card [product]="product" />
}
}
} @empty {
<p>Ta kategoria nie ma produktów</p>
}
</section>
} @empty {
<p>Brak kategorii do wyświetlenia</p>
}
}Optymalizacje wydajności z nową składnią
Nowa składnia control flow przynosi znaczące ulepszenia wydajności:
Szybszy Change Detection
Bloki @for z wyrażeniem track umożliwiają Angular bardziej efektywne porównywanie kolekcji. Framework może pominąć sprawdzanie elementów, które się nie zmieniły, bazując na tożsamości śledzonej wartości.
Lepsza minifikacja
Ponieważ składnia blokowa nie wymaga importów z CommonModule, nieużywane bloki mogą być całkowicie usunięte podczas budowania produkcyjnego.
Optymalizacja @defer
Składnia control flow współpracuje z @defer dla leniwego ładowania:
@defer (on viewport) {
@for (item of heavyItems(); track item.id) {
<app-heavy-component [data]="item" />
}
} @placeholder {
<div class="placeholder">Ładowanie...</div>
}Migracja z dyrektyw strukturalnych
Proces migracji jest prosty dzięki wbudowanemu schematowi:
ng generate @angular/core:control-flowSchematyk automatycznie przekształca:
| Stara składnia | Nowa składnia |
|---|---|
*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; trackBy: trackFn" | @for (item of items; track trackFn($index, item)) { } |
[ngSwitch] + *ngSwitchCase | @switch + @case |
Gotowy na rozmowy o Angular?
Ćwicz z naszymi interaktywnymi symulatorami, flashcards i testami technicznymi.
Pytania rekrutacyjne dotyczące Angular Control Flow
Poniżej znajduje się zestaw pytań często zadawanych na rozmowach kwalifikacyjnych dotyczących nowej składni control flow.
Pytanie 1: Dlaczego wyrażenie track jest obowiązkowe w @for?
Odpowiedź: Wyrażenie track jest obowiązkowe, ponieważ zapewnia algorytmowi różnicowania Angular unikalny identyfikator dla każdego elementu w kolekcji. Pozwala to frameworkowi efektywnie określić, które elementy DOM należy ponownie wykorzystać, zaktualizować lub usunąć podczas zmian w kolekcji. Bez trackingu Angular musiałby ponownie renderować całą listę przy każdej zmianie, co znacząco wpływałoby na wydajność.
Pytanie 2: Jak @if obsługuje głęboko zagnieżdżone właściwości opcjonalne?
Odpowiedź: Blok @if wspiera aliasowanie zmiennych za pomocą słowa kluczowego as, które pozwala wyodrębnić wartość z zagnieżdżonego wyrażenia i używać jej w bloku. Składnia to @if (wyrażenie; as alias). Aliasowana zmienna jest dostępna tylko wtedy, gdy wyrażenie jest prawdziwe, co eliminuje potrzebę powtarzania operatorów opcjonalnego łańcuchowania w szablonie.
Pytanie 3: Czym różni się @switch od *ngSwitch?
Odpowiedź: @switch jest wbudowany w framework i nie wymaga importów. Używa natywnej składni blokowej zamiast dyrektyw atrybutowych. Eliminuje potrzebę opakowujących elementów ng-container. Używa ścisłego porównania (===), co zapobiega niespodziewanym dopasowaniom związanym z koercją typów. Każdy @case i @default to niezależny blok, co poprawia czytelność kodu.
Pytanie 4: Jak uzyskać dostęp do indeksu i innych metadanych w @for?
Odpowiedź: Blok @for udostępnia zmienne kontekstowe poprzez składnię let: @for (item of items; track item.id; let i = $index, f = $first). Dostępne zmienne to $index, $first, $last, $even, $odd i $count. Te zmienne mogą być przypisane do lokalnych aliasów i używane w bloku.
Pytanie 5: Czy można używać @for z obiektami Map i Set?
Odpowiedź: Tak, blok @for iteruje po dowolnym obiekcie implementującym protokół iteratora JavaScript, w tym Map, Set i generatorach. Dla Map iteracja zwraca pary [klucz, wartość], które można destrukturyzować w szablonie.
Pytanie 6: Jak działa @empty i kiedy jest wywoływany?
Odpowiedź: Blok @empty jest wyświetlany gdy kolekcja w @for jest pusta (ma zerową długość) lub gdy iterowalny obiekt nie zwraca żadnych elementów. Jest to wbudowany odpowiednik sprawdzania items.length === 0 i renderowania alternatywnej treści. Blok @empty jest opcjonalny.
Pytanie 7: Jakie są korzyści wydajnościowe nowej składni control flow?
Odpowiedź: Nowa składnia oferuje kilka korzyści wydajnościowych: brak narzutu importów (zero dodatkowego kodu dla dyrektyw), lepszy tree-shaking (nieużywane ścieżki kodu są eliminowane), bardziej efektywny change detection dzięki obowiązkowemu trackingowi, oraz możliwość przyszłych optymalizacji kompilatora, ponieważ składnia jest parsowana statycznie zamiast interpretowana w runtime.
Najlepsze praktyki dla składni Control Flow
Podczas implementacji nowej składni control flow warto przestrzegać kilku zasad:
- Zawsze używaj unikalnych identyfikatorów w track - preferuj
track item.idzamiasttrack $indexdla kolekcji, które mogą się zmieniać - Wykorzystuj @empty dla lepszego UX - zawsze definiuj stan pustej listy dla lepszego doświadczenia użytkownika
- Unikaj złożonej logiki w wyrażeniach - przenieś skomplikowane obliczenia do komponentu
- Stosuj aliasowanie dla zagnieżdżonych właściwości - używaj
asdla głęboko zagnieżdżonych wyrażeń opcjonalnych - Migruj stopniowo - obie składnie mogą współistnieć, więc można migrować plik po pliku
Podsumowanie
Składnia control flow w Angular reprezentuje fundamentalną zmianę w sposobie pisania szablonów. Bloki @if, @for i @switch oferują bardziej intuicyjną składnię inspirowaną JavaScript, eliminują potrzebę importowania CommonModule i zapewniają lepszą wydajność dzięki obowiązkowemu trackingowi i optymalizacjom kompilatora. Dla zespołów rozpoczynających nowe projekty Angular, nowa składnia powinna być domyślnym wyborem. Dla istniejących projektów, automatyczna migracja za pomocą schematu ng generate @angular/core:control-flow umożliwia płynne przejście bez ryzyka regresji.
Znajdziesz błąd w Angular?
Prawdziwy fragment kodu, ukryty błąd, jedna próba dziennie. Bez konta, żeby spróbować.

Autor:
Anthony Fillion-MailletZałożyciel SharpSkill
Programista fullstack od ponad 10 lat. Prowadzi SharpSkill i odpowiada za wszystko, co się tu ukazuje.
Zaktualizowano 3 września 2026
Tagi
Udostępnij
Powiązane artykuły

Zaawansowany Dependency Injection w Angular 2026: Providers, Tokens i Pytania Rekrutacyjne
Kompleksowy przewodnik po zaawansowanych mechanizmach Dependency Injection w Angular. Providers, InjectionToken, hierarchia injectorów oraz najczęstsze pytania na rozmowach kwalifikacyjnych.

NgRx Signal Store vs Klasyczny NgRx w 2026: Który Wybrać?
Kompleksowe porównanie NgRx Signal Store i klasycznego NgRx do zarządzania stanem w Angular. Praktyczne przykłady kodu i rekomendacje na rok 2026.

RxJS w Angularze 2026: operatory, Subjecty i interop z Signals
RxJS w Angularze 2026: opanuj operatory, Subjecty i wzorce interoperacyjności z Signals używane na produkcji oraz pytania rekrutacyjne, które padają najczęściej.