Angular - dyrektywy strukturalne ngIf, ngFor i ngSwitch

Stronę tą wyświetlono już: 19 razy

Wstęp

Dyrektywy strukturalne służą do sterowania wyglądem widoku strony. Każda taka dyrektywa wyróżnia się znacznikiem * wstawianym przed jej nazwą. Ważne jest aby pamiętać, że Angular umożliwia nałożenie na jeden element HTML tylko jednej dyrektywy strukturalnej. Dostępne dyrektywy strukturalne to:

  • ngIf - steruje elementem drzewa DOM usuwając lub dodając element gdy dany warunek jest spełniony;
  • ngSwitch - przełącza widoki ale nie usuwa z kodu strony elementu przełączanego a jedynie go wykomentowuje;
  • ngFor - steruje elementem drzewa DOM poprzez iterowanie przez tablicę obiektów

Dyrektywa ngIf

Jak już wspominałem dyrektywa ngIf usuwa lub dodaje dany element do drzewa DOM. Sposób jej użycia można zobaczyć poniżej:

Listing 1
  1. <button type="button" (click)="switchToggle()">Przełącz</button>
  2. <div *ngIf="toggle else enabled">Włączny widok</div>
  3. <ng-template #enabled>Wyłączony widok</ng-template>

W powyższym kodzie ostatni element HTML ma znacznik #enabled, który oznacza zmienną podpiętą pod ten konkretny element drzewa DOM, za pomocą której można się do tego elementu z poziomu kodu HTML odwoływać. Zmienna ta została wykorzystana w dyrektywie ngIf do przełączania widoku.

Namiastka tego, jak by to działało przynajmniej wizualnie pokazana została poniżej. Należy jednak mieć na uwadze, że poniższy efekt został uzyskany przy wykorzystaniu czystego JavaScript-u.

Dla porównania kod generujący powyższy przykład z wykorzystaniem JavaScript-u wygląda tak:

Listing 2
  1. <button id="toggleButton">Przełącz</button>
  2. <div id="addElementView">
  3. </div>
  4. <script>
  5. let toggle = false;
  6. function switchToggle() {
  7. toggle = !toggle;
  8. let view = document.querySelector('#addElementView');
  9. view.innerHTML = '';
  10. let element = document.createElement('div');
  11. element.innerText = toggle ? 'Włączony widok' : 'Wyłączony widok';
  12. view.appendChild(element);
  13. }
  14. switchToggle();
  15. document.querySelector('#toggleButton').addEventListener('click', switchToggle);
  16. </script>

Dyrektywa ngSwitch

Dyrektywa ngSwitch pozwala na przełączanie wyświetlanych elementów. Oto przykład kodu HTML wykorzystującego tę dyrektywę:

Listing 3
  1. <div [ngSwitch]="value">
  2. <div *ngSwitchCase="0">Wartość 0</div>
  3. <div *ngSwitchCase="1">Wartość 1</div>
  4. <div *ngSwitchCase="2">Wartość 2</div>
  5. </div>
  6. <button type="button" (click)="changeValue()">Przełącz zmienną sterującą value = {{ value }}</button>

Natomiast w klasie komponentu potrzebne jest jeszcze pole o nazwie value i metoda przełączająca wartość tego pola:

Listing 4
  1. value: number = 1;
  2. changeValue() {
  3. this.value = (this.value + 1) % 3;
  4. }

Ważne jest, aby zdawać sobie sprawę, że ta dyrektywa nie usuwa elementów z drzewa DOM a jedynie je wykomentowuje. Oto jak wygląda kod HTML elementów sterowanych przez tą dyrektywę:

Listing 5
  1. <div _ngcontent-eyy-c3="" ng-reflect-ng-switch="0"><!--bindings={
  2. "ng-reflect-ng-switch-case": "0"
  3. }--><div _ngcontent-eyy-c3="">Wartość 0</div><!--bindings={
  4. "ng-reflect-ng-switch-case": "1"
  5. }--><!--bindings={
  6. "ng-reflect-ng-switch-case": "2"
  7. }--></div>

Jak widać kod ten wykomentowuje te elementy, dla których wartość warunkowa nie została spełniona.

Dyrektywa ngFor

Ostatnia dyrektywa daje możliwość wstawiania w kodzie elementów np. tablicy wartości, które mogą być obiektami lub zwykłymi wartościami liczbowymi. Oto jak w łatwy sposób można wypisywać elementy zapisane w zmiennej tablicowej wewnątrz kodu HTML komponentu z wykorzystaniem dyrektywy ngFor:

Listing 6
  1. <table>
  2. <tr>
  3. <th *ngFor="let title of tableHeaderTitles">{{ title }}</th>
  4. </tr>
  5. <tr *ngFor="let car of cars">
  6. <td>{{ car.brand }}</td>
  7. <td>{{ car.maxSpeed }}</td>
  8. <td>{{ car.acceleration }}</td>
  9. <td>{{ car.power}} [KM]</td>
  10. </tr>
  11. </table>

W kodzie klasy komponentu potrzebny będzie interfejs do przechowywania obiektów samochodu:

Listing 7
  1. export interface Car{
  2. brand: string;
  3. maxSpeed: number;
  4. acceleration: number;
  5. power: number;
  6. }

Natomiast w kodzie klasy potrzebne są pola, przechowujące tytuły nagłówka tabeli oraz jej dane:

Listing 8
  1. tableHeaderTitles: string[] = [ 'Marka samochodu', 'V Max [km/h]', 'Przyspieszenie w s od 0 do 100 km/h', 'Moc KM'];
  2. cars: Car[] = [
  3. { brand: 'Ford Mustang', maxSpeed: 250, acceleration: 6.5, power: 250 },
  4. { brand: 'Ford T', maxSpeed: 30, acceleration: null, power: 30 },
  5. { brand: 'Ferrari F50', maxSpeed: 325, acceleration: 3.7, power: 520 }
  6. ];

Przybliżony wynik działania takiego kodu można zobaczyć poniżej (formatowanie pozostawiłem nie ruszone dając do zrozumienia, że tablica w ten sposób wygenerowana wymaga jeszcze dopracowania przy pomocy styli).

Marka samochoduV Max [km/h]Przyspieszenie w s od 0 do 100 km/hMoc KM
Ford Mustang2506.5250 [KM]
Ford T3030 [KM]
Ferrari F503253.7520 [KM]

Dyrektywa ngFor umożliwia również dostęp do kilku przydatnych zmiennych takich jak:

  • index - indeks elementu;
  • even - zmienna typu boolean zawierająca true gdy indeks rekordu jest liczbą parzystą;
  • odd -zmienna typu boolean zawierająca true gdy indeks rekordu jest liczbą nieparzystą;
  • first - zmienna przechowująca pierwszy rekord danych;
  • last - zmienna przechowująca ostatni rekord danych;
  • trackBy - parametr, do którego można przypisać funkcję, która zoptymalizuje odświeżanie danych w tabeli poprzez wykrywanie zmiany np. po id

Prosty przykład kodu, który wykorzystuje część powyżej wymienionych zmiennych wygląda w HTML-u tak:

Listing 9
  1. <table>
  2. <tr>
  3. <th *ngFor="let title of tableHeaderTitles">{{ title }}</th>
  4. </tr>
  5. <tr *ngFor="let car of cars; let i = index; let even = even; let odd = odd" [ngClass]="{ 'odd': odd, 'even': even }">
  6. <td>{{ i + 1 }}</td>
  7. <td>{{ car.brand }}</td>
  8. <td>{{ car.maxSpeed }}</td>
  9. <td>{{ car.acceleration }}</td>
  10. <td>{{ car.power}} [KM]</td>
  11. </tr>
  12. </table>

Zaś w kodzie klasy komponentu:

Listing 10
  1. tableHeaderTitles: string[] = [ 'Nr.', 'Marka samochodu', 'V Max [km/h]', 'Przyspieszenie w s od 0 do 100 km/h', 'Moc KM'];
  2. cars: Car[] = [
  3. { brand: 'Ford Mustang', maxSpeed: 250, acceleration: 6.5, power: 250 },
  4. { brand: 'Ford T', maxSpeed: 30, acceleration: null, power: 30 },
  5. { brand: 'Ferrari F50', maxSpeed: 325, acceleration: 3.7, power: 520 }
  6. ];

Dyrektywa ngClass umożliwia przełączanie klas styli w zależności od zmiennych odd i even.

Nr.Marka samochoduV Max [km/h]Przyspieszenie w s od 0 do 100 km/hMoc KM
1Ford Mustang2506.5250 [KM]
2Ford T3030 [KM]
3Ferrari F503253.7520 [KM]

Komentarze