Wprowadzenie

W Angular 8 ngSwitch jest dyrektywą strukturalną, która jest używana do dodawania/usuwania elementów drzewa DOM. Jest podobna do tej samej instrukcji(switch) w języku C#. Podobna jest również zasada działania – przełączanie odbywa się na podstawie zdefiniowanego wyrażenia.

Składania przedstawia się następująco:

<selector [ngSwitch]="wyrażenie">
    <selektor_wewnetrzny *ngSwitchCase="pasujace_wyrazenie_1">…</selektor_wewnetrzny>
    <selektor_wewnetrzny *ngSwitchCase="pasujace_wyrazenie_2">…</selektor_wewnetrzny>
    <selektor_wewnetrzny *ngSwitchCase="pasujace_wyrazenie_3">…</selektor_wewnetrzny>
    <selektor_wewnetrzny *ngSwitchDefault>…</selektor_wewnetrzny>
</selector>

ngSwitchCase oraz ngSwitchDefault

Dyrektywa ngSwitchCase umieszczana jest w elemencie wewnętrznym kontenera i pozwala na przygotowania wyrażenia będącego dopasowaniem do warunku. Za każdym razem gdy dojdzie do spełnia warunku dany element wewnętrzny zostanie dodany do drzewa DOM. Wszystkie pozostałe elementy zostaną usunięte z DOM.

W Angular 8 możemy również posługiwać się dyrektywą ngSwitchDefault. Element taki zostanie wyświetlony tylko wtedy, gdy nie zostanie znalezione żadne dopasowanie. Element ten może zostać umieszczony w dowolnym miejscu wewnątrz kontenera – nie musi być to element ostatni. W naszym zapisie może pojawić się więcej elementów domyślnych – wówczas, kiedy nie dojdzie do pasowania, każdy z nich zostanie wyświetlony.

Warto również wspomnieć, że w kontenerze poza elementami ngSwitchCase oraz ngSwitchDefault możemy zdefiniować inne elementy – zostane one wyświetlone w niezmienionej postaci.

Przykłady

Zmieniamy operatory logiczne w projekcie, który przygotowaliśmy we wpisie Angular 8: dyrektywa ngIf. Tak powinien wyglądać ekran główny przed przejściem dalej: Angular 8: dyrektywa ngSwitch

Następnie do naszego komponentu dodamy poniższy kod stanowiący definicję kolekcji oraz wartość wyrażenia dopasowania:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-ng-switch',
  templateUrl: './ng-switch.component.html',
  styleUrls: ['./ng-switch.component.css']
})

export class NgSwitchComponent implements OnInit {  
  title: string;
  isTimeForThisComponent: boolean;
  cars: Cars[];
  selectedCar: number;

  constructor() { 
    this.isTimeForThisComponent = true;

    if (this.isTimeForThisComponent){
      this.title = 'Tematem tego wpisu jest dyrektywa ng-switch';
    } else {
      this.title = 'Temat tego wpisu nie dotyczy dyrektywy ng-switch';
    }

    this.cars = [
      {id: 1, name: 'Audi RS6 C7'},
      {id: 2, name: 'Pagani Zonda F Roadster'},
      {id: 3, name: 'Nissan GTR R34'}
    ];
    this.selectedCar = 1;
  }

  ngOnInit() {
  }
}

class Cars {
  id: number;
  name: string;
}

Celem naszego prostego projektu będzie wybieranie z listy rozwijalnej dostępnych modeli samochodów a dyrektywę ngSwitch wykorzystamy do wyświetlenia przykładowego zdjęcia wybranego samochodu. Implementacja może wyglądać w poniższy sposób:

<p *ngIf="isTimeForThisComponent" class="article-subject">
    {{title}}
</p>

<p *ngIf="!isTimeForThisComponent" class="not-article-subject">
    {{title}}
</p>

<div id="switch-test-container" *ngIf="isTimeForThisComponent"
        style="width:860px;margin-left: auto;margin-right: auto;">
    <!-- [(ngModel)] - dwukierunkowe wiązanie -> w kolejnych wpisie omówimy bardziej szczegółowo -->
    <select [(ngModel)]="selectedCar">
        <!-- Wykorzystujemy dyrektywę ngFor celem dodania elementów do wybrania -->
        <option *ngFor="let car of cars;" [value]="car.id">{{car.name}}</option>
    </select>

    <!-- Dyrektywę ngSwitch używamy do wyświetlenia odpowiedniego zdjęcia samochodu -->
    <div id="car-images" [ngSwitch]="selectedCar">
        <div *ngSwitchCase="1">
            <img width="100%"
                    src="https://image.shutterstock.com/z/stock-photo-audi-rs-avant-c-in-motion-kiev-ukraine-june-editorial-photo-662321233.jpg">
        </div>
        <div *ngSwitchCase="2">
            <img width="100%"
                    src="https://image.shutterstock.com/z/stock-photo-pagani-sport-car-at-dreamcars-asia-expo-malaysia-637009.jpg">
        </div>
        <div *ngSwitchCase="3">
            <img width="100%"
                    src="https://image.shutterstock.com/z/stock-photo-hakone-japan-november-nissan-skyline-gtr-vspec-bnr-cruising-famous-hakone-1505614688.jpg">
        </div>
        <div *ngSwitchDefault>
            <img width="100%"
                    src="https://image.shutterstock.com/z/stock-photo-mortgage-default-stamp-depicting-home-loan-overdue-or-shortfall-failure-to-pay-off-line-of-credit-1362477851.jpg">
        </div>
    </div>
</div>
            

Zanim jednak pójdziemy dalej musimy skupić się na na wiązaniu dwukierunkowym. Aby uniknać błędów kompilacji musimy dokonać importu jednego pakietu, który pozwala na użycie poniższego zapisu:

 <!-- [(ngModel)] - dwukierunkowe wiązanie -> w kolejnych wpisie omówimy bardziej szczegółowo -->
<select [(ngModel)]="selectedCar">
    <!-- Wykorzystujemy dyrektywę ngFor celem dodania elementów do listy rozwijalnej -->
    <option *ngFor="let car of cars;" [value]="car.id">{{car.name}}</option>
</select>
W tym celu nieznacznie zmodyfikujemy plik app.module.ts (spójrzcie na komentarze w kodzie):
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppRoutingModule } from './app-routing.module';
import { DashboardComponent } from './Dashboard/dashboard.component';
import { NgIfComponent } from './components/ng-if/ng-if.component';
import { NgSwitchComponent } from './components/ng-switch/ng-switch.component';
import { NgForComponent } from './components/ng-for/ng-for.component';
// Musimy zaimportować pakiet FormsModule aby uzywać dwukierunkowego wiązania - o tym będzie więcej w kolejnym wpisie
// Poniższy zapis w pliku: ng-switch.component.html ->  <select [(ngModel)]="selectedCar">
import { FormsModule } from '@angular/forms';

@NgModule({
  declarations: [
    DashboardComponent,
    NgIfComponent,
    NgSwitchComponent,
    NgForComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    // Dodany pakiet
    FormsModule
  ],
  providers: [],
  bootstrap: [DashboardComponent]
})
export class AppModule { }
A tak prezentuje się działająca aplikacja: