Dyrektywy warunkowe w Angularze – @if i *ngIf

1. Czym są dyrektywy warunkowe?

Dyrektywy warunkowe to narzędzia w Angularze, które pozwalają na pokazywanie lub ukrywanie elementów na stronie w zależności od określonych warunków. To jest bardzo przydatne, gdy chcemy, aby część treści była widoczna tylko w określonych sytuacjach.

Przykłady zastosowań:

  • Pokazanie komunikatu o błędzie tylko gdy formularz jest niepoprawny
  • Wyświetlenie menu administratora tylko dla administratorów
  • Ukrycie przycisku „Usuń” dla gości
  • Pokazanie dodatkowych informacji po kliknięciu przycisku

2. Nowoczesna składnia @if (Angular 17+)

Angular wprowadził nową, lepszą składnię@if. Jest ona:

  • Bardziej czytelna – przypomina normalne warunki w programowaniu
  • Nie wymaga importów – nie trzeba dodawać żadnych modułów
  • Wydajniejsza – Angular działa szybciej
  • Prostsza w użyciu – szczególnie przy złożonych warunkach

Jak działa @if?

Składnia @if sprawdza czy warunek jest prawdziwy (true) czy fałszywy (false):

  • Jeśli true – element zostaje dodany do strony
  • Jeśli false – element zostaje usunięty ze strony

Ważne: Element jest całkowicie usuwany z DOM, nie tylko ukrywany!

Podstawowa składnia @if

@if (warunek) {
  <div>Element pokazywany gdy warunek jest prawdziwy</div>
}

Pierwszy przykład

// Komponent TypeScript
import { Component } from '@angular/core';

@Component({
  selector: 'app-film-component',
  standalone: true,
  imports: [], // Nie potrzebujemy żadnych importów dla @if!
  templateUrl: './film-component.component.html',
  styleUrl: './film-component.component.css'
})
export class FilmComponentComponent {
  showDetails = false;
  
  toggleDetails() {
    this.showDetails = !this.showDetails;
  }
}
<!-- Szablon HTML -->
<div class="container">
  <h2>Informacje o filmie</h2>
  
  <button (click)="toggleDetails()" class="btn btn-primary">
    Pokaż/ukryj szczegóły
  </button>
  
  <!-- Element pokazywany warunkowo -->
  @if (showDetails) {
    <div class="alert alert-info mt-3">
      <h4>Szczegóły filmu</h4>
      <p>Tutaj są dodatkowe informacje o filmie...</p>
    </div>
  }
</div>

3. Przykłady z @if – od prostych do bardziej skomplikowanych

Przykład 1: Proste pokazywanie/ukrywanie

export class SimpleExampleComponent {
  isVisible = false;
  
  toggle() {
    this.isVisible = !this.isVisible;
  }
}
<div class="container">
  <h3>Przykład 1: Podstawowe użycie</h3>
  
  <button (click)="toggle()" class="btn btn-primary">
    Przełącz widoczność
  </button>
  
  @if (isVisible) {
    <div class="alert alert-info mt-3">
      <h4>Jestem widoczny! 👀</h4>
      <p>Ten blok pojawia się tylko gdy isVisible = true</p>
    </div>
  }
</div>

Przykład 2: @if z @else

export class ToggleExampleComponent {
  showMessage = true;
  
  toggleMessage() {
    this.showMessage = !this.showMessage;
  }
}
<div class="container">
  <h3>Przykład 2: @if z @else</h3>
  
  <button (click)="toggleMessage()" class="btn btn-primary">
    Zmień wiadomość
  </button>
  
  @if (showMessage) {
    <div class="alert alert-success mt-3">
      <p>✅ To jest pierwsza wiadomość!</p>
    </div>
  } @else {
    <div class="alert alert-warning mt-3">
      <p>⚠️ To jest alternatywna wiadomość!</p>
    </div>
  }
</div>

Przykład 3: @if z @else if – role użytkowników

export class UserRoleComponent {
  userRole = 'guest'; // 'admin', 'user', 'guest'
  
  setRole(role: string) {
    this.userRole = role;
  }
}
<div class="container">
  <h3>Przykład 3: Różne role użytkowników</h3>
  
  <div class="mb-3">
    <button (click)="setRole('admin')" class="btn btn-danger me-2">
      Zostań adminem
    </button>
    <button (click)="setRole('user')" class="btn btn-primary me-2">
      Zostań użytkownikiem
    </button>
    <button (click)="setRole('guest')" class="btn btn-secondary">
      Zostań gościem
    </button>
  </div>
  
  @if (userRole === 'admin') {
    <div class="alert alert-danger">
      <h4>🔑 Panel Administratora</h4>
      <p>Masz pełne uprawnienia do zarządzania systemem!</p>
      <button class="btn btn-outline-danger">Zarządzaj użytkownikami</button>
    </div>
  } @else if (userRole === 'user') {
    <div class="alert alert-primary">
      <h4>👤 Panel Użytkownika</h4>
      <p>Jesteś zalogowanym użytkownikiem. Możesz dodawać filmy i oceny.</p>
      <button class="btn btn-outline-primary">Mój profil</button>
    </div>
  } @else {
    <div class="alert alert-secondary">
      <h4>🌐 Tryb Gościa</h4>
      <p>Przeglądasz jako gość. Zaloguj się, aby odblokować więcej funkcji!</p>
      <button class="btn btn-outline-secondary">Zaloguj się</button>
    </div>
  }
</div>

Przykład 4: Ocena filmu z różnymi komunikatami

export class FilmRatingComponent {
  rating = 0;
  
  setRating(value: number) {
    this.rating = value;
  }
  
  clearRating() {
    this.rating = 0;
  }
}
<div class="container">
  <h3>Przykład 4: System oceniania filmu</h3>
  
  <div class="mb-3">
    <p>Oceń film (1-5 gwiazdek):</p>
    <button (click)="setRating(1)" class="btn btn-outline-warning me-1">⭐</button>
    <button (click)="setRating(2)" class="btn btn-outline-warning me-1">⭐⭐</button>
    <button (click)="setRating(3)" class="btn btn-outline-warning me-1">⭐⭐⭐</button>
    <button (click)="setRating(4)" class="btn btn-outline-warning me-1">⭐⭐⭐⭐</button>
    <button (click)="setRating(5)" class="btn btn-outline-warning me-1">⭐⭐⭐⭐⭐</button>
    <button (click)="clearRating()" class="btn btn-outline-secondary ms-2">Wyczyść</button>
  </div>
  
  @if (rating === 0) {
    <div class="alert alert-light">
      <p>👆 Wybierz ocenę powyżej, aby zobaczyć komentarz!</p>
    </div>
  } @else if (rating === 1) {
    <div class="alert alert-danger">
      <h5>😞 Bardzo słabo! (1/5)</h5>
      <p>Ten film naprawdę Ci się nie podobał...</p>
    </div>
  } @else if (rating === 2) {
    <div class="alert alert-warning">
      <h5>😐 Słabo (2/5)</h5>
      <p>Film był poniżej oczekiwań. Można było zrobić to lepiej.</p>
    </div>
  } @else if (rating === 3) {
    <div class="alert alert-info">
      <h5>🙂 W porządku (3/5)</h5>
      <p>Przeciętny film. Nie najgorszy, ale nie najlepszy.</p>
    </div>
  } @else if (rating === 4) {
    <div class="alert alert-success">
      <h5>😊 Dobry film! (4/5)</h5>
      <p>Film Ci się podobał! Warto było obejrzeć.</p>
    </div>
  } @else if (rating === 5) {
    <div class="alert alert-success">
      <h5>🤩 DOSKONAŁY! (5/5)</h5>
      <p>To był fantastyczny film! Polecasz go wszystkim znajomym!</p>
    </div>
  }
</div>

4. Alternatywna składnia *ngIf (starsze projekty)

W starszych projektach może spotkasz tradycyjną składnię *ngIf. Warto ją znać, ale zalecamy używanie @if w nowych projektach.

Porównanie składni

// Komponent wspólny dla obu wersji
export class ComparisonComponent {
  showMessage = true;
  userRole = 'user';
}

Wersja z @if (ZALECANA)

@if (showMessage) {
  <div class="alert alert-info">Wiadomość widoczna</div>
} @else {
  <div class="alert alert-warning">Wiadomość ukryta</div>
}

@if (userRole === 'admin') {
  <p>Panel admina</p>
} @else if (userRole === 'user') {
  <p>Panel użytkownika</p>
} @else {
  <p>Panel gościa</p>
}

Wersja z *ngIf (STARSZA)

<!-- Wymaga import { CommonModule } w komponencie! -->
<div *ngIf="showMessage; else hiddenMessage" class="alert alert-info">
  Wiadomość widoczna
</div>
<ng-template #hiddenMessage>
  <div class="alert alert-warning">Wiadomość ukryta</div>
</ng-template>

<!-- Mniej czytelne dla wielu warunków -->
<div *ngIf="userRole === 'admin'">Panel admina</div>
<div *ngIf="userRole === 'user'">Panel użytkownika</div>
<div *ngIf="userRole !== 'admin' && userRole !== 'user'">Panel gościa</div>

Kluczowe różnice

Cecha@if (NOWA)*ngIf (STARA)
ImportNie wymaga importówWymaga CommonModule
Składnia@if (warunek) { }*ngIf="warunek"
ElseProste @else { }Wymaga ng-template
Else ifNaturalne @else ifTrudne do zrobienia
CzytelnośćBardzo czytelneMniej czytelne
WydajnośćLepszaDobra

5. Najlepsze praktyki

✅ Co robić:

  1. Używaj @if w nowych projektach – jest prostszy i lepszy
  2. Twórz opisowe nazwy zmiennych: showDetails, isLoggedIn, hasPermission
  3. Używaj getterów dla złożonych warunków:
  1. Grupuj powiązane warunki zamiast robić wiele osobnych @if

❌ Czego unikać:

  1. Zbyt długich wyrażeń w szablonie – przenieś logikę do komponentu
  2. Zagnieżdżania wielu poziomów – lepiej podziel na mniejsze komponenty
  3. Powtarzania warunków – użyj zmiennych lub getterów

6. Teoria: Jak Angular obsługuje warunki

Gdy używasz @if, Angular:

  1. Sprawdza warunek za każdym razem gdy zmieni się stan komponentu
  2. Dodaje element do DOM gdy warunek staje się true
  3. Usuwa element z DOM gdy warunek staje się false
  4. Pamięta stan i nie przebudowuje niepotrzebnie

To znaczy, że:

  • Element NIE jest tylko ukrywany (jak w CSS display: none)
  • Element jest fizycznie usuwany ze strony
  • To oszczędza pamięć i przyspiesza stronę

7. Ćwiczenia do samodzielnego wykonania

  1. Kalkulator wieku filmu: Wyświetl różne komunikaty w zależności od tego, czy film jest nowy (0-2 lata), średni (3-10 lat), czy stary (ponad 10 lat)
  2. System statusów zamówienia: Stwórz komunikaty dla różnych statusów: „złożone”, „w realizacji”, „wysłane”, „dostarczone”
  3. Walidacja hasła: Sprawdź czy hasło ma odpowiednią długość i wyświetl komunikaty pomocnicze
  4. Quiz o filmach: Zadaj pytanie i pokaż różne odpowiedzi w zależności od wyboru użytkownika
  5. Profil użytkownika: Wyświetl różne sekcje profilu w zależności od poziomu konta (darmowe/premium)

8. Podsumowanie

Dyrektywy warunkowe to podstawowe narzędzie w Angularze do tworzenia dynamicznych interfejsów.