Rezepte für ngFor-Listen

In diesem Kapitel befinden sich Rezepte, die uns bei der Arbeit mit Listen helfen, die in der View mittels der NgFor-Direktive angezeigt werden. Wie man solche Listen anzeigen kann, wird im Rezept “Liste von Daten anzeigen” dargestellt.

Mit dem Index von ngFor-Elementen arbeiten

Problem

Ich möchte den Index der ngFor-Elemente in der View anzeigen.

Zutaten

Lösung

app.component.ts
 1 ...
 2 
 3 @Component({
 4   selector: 'app-root',
 5   template: `
 6     <ul>
 7       <li *ngFor="let user of users; let i = index">
 8         Index: {{i}},
 9         Name: {{user.firstname}} {{user.lastname}}
10       </li>
11     </ul>
12   `
13 })
14 
15 ...

Erklärung:

Die Anpassungen betreffen nur die template-Eigenschaft der Komponente. Der Rest bleibt gleich.

  • Zeile 7: Definiert eine lokale Variable “i”, die den Index für das aktuelle Element referenziert. In diesem Fall ist index ein spezielles ngFor-Konstrukt
  • Zeile 8: Die lokale Variable “i” für den Index wird mittels Interpolation angezeigt

Diskussion

Hier zeigen wir den Index nur in der View an. Natürlich können wir die lokale Variable “i” auch einer Methode übergeben oder diese nutzen, um etwas zu berechnen. Z. B. können wir in Zeile 8 eine Eins zu der Variable “i” addieren, so dass die Anzeige mit 1 statt 0 beginnt. Der Ausdruck dafür wäre {{i + 1}}.

Code

Code auf Github. Dort werden auch die weiteren möglichen Schreibweisen der NgFor-Direktive mit Index gezeigt.

Live Demo auf angular2kochbuch.de

Weitere Ressourcen

Gerade und ungerade ngFor-Elemente unterscheiden

Problem

Ich möchte, dass gerade Elemente meiner Liste eine andere Farbe als ungerade erhalten.

Zutaten

Lösung

app.component.ts
 1 ...
 2 
 3 @Component({
 4   selector: 'app-root',
 5   styles: [
 6     '.red { color: red; }',
 7     '.green { color: green; }'
 8   ],
 9   template: `
10     <ul>
11       <li *ngFor="let user of users; let isEven = even; let isOdd = odd"
12           [ngClass]="{red: isOdd, green: isEven}">
13         Name: {{user.firstname}} {{user.lastname}}
14       </li>
15     </ul>
16   `
17 })
18 
19 ...

Erklärung:

Die Anpassungen betreffen nur die template-Eigenschaft der Komponente. Der Rest bleibt gleich.

  • Zeilen 6-7: Definition von CSS-Klassen
  • Zeile 11: Definiert lokale Variablen “isEven” und “isOdd” die, je nachdem ob das aktuelle Element gerade oder ungerade ist, true oder false sind. In diesem Fall sind even und odd spezielle ngFor-Konstrukte
  • Zeile 12: Hier werden, je nachdem, ob das aktuelle Element gerade oder ungerade ist, die Klassen “green” oder “red” gesetzt

Diskussion

Hier nutzen wir die Information, ob das aktuelle Element gerade oder ungerade ist, um die richtige CSS-Klasse zu setzen. Natürlich können wir die lokalen Variablen “isOdd” und “isEven” auch einer Methode übergeben oder diese nutzen, um z. B. nur gerade oder nur ungerade Elemente anzuzeigen.

Code

Code auf Github. Dort werden auch die weiteren möglichen Schreibweisen der NgFor-Direktive mit even/odd gezeigt.

Live Demo auf angular2kochbuch.de

Weitere Ressourcen

Das erste und das letzte ngFor-Element finden

Problem

Ich möchte das erste und das letzte Element meiner Liste farblich hervorheben.

Zutaten

Lösung

app.component.ts
 1 ...
 2 
 3 @Component({
 4   selector: 'app-root',
 5   styles: [
 6       '.first { background-color: red; }',
 7       '.last { background-color: green; }'
 8   ],
 9   template: `
10     <ul>
11       <li *ngFor="let user of users; let isLast = last; let isFirst = first"
12           [ngClass]="{first: isFirst, last: isLast}">
13         Name: {{user.firstname}} {{user.lastname}}
14       </li>
15     </ul>
16   `
17 })
18 
19 ...

Erklärung:

Die Anpassungen betreffen nur die template-Eigenschaft der Komponente. Der Rest bleibt gleich.

  • Zeilen 6-7: Definition von CSS-Klassen
  • Zeile 11: Definiert die lokalen Variablen “isLast” und “isFirst”. Die isLast-Variable ist true, wenn das aktuelle Element das Letzte in der Liste ist, ansonsten ist sie false. Die isFirst-Variable ist true, wenn das aktuelle Element das Erste in der Liste ist, ansonsten ist sie false. In diesem Fall sind last und first spezielle ngFor-Konstrukte
  • Zeile 12: Hier wird die Klasse “first” gesetzt, falls das aktuelle Element das Erste der Liste ist oder “last” falls es das letzte Element der Liste ist

Diskussion

Hier nutzen wir die Information, ob das aktuelle Element das Erste oder das Letzte in der Liste ist, um die entsprechenden Elemente farblich hervorzuheben. Wie auch in den vorherigen zwei Rezepten können wir hier die Information, ob ein Element das Erste oder das Letzte einer Liste ist, z. B. an eine Methode übergeben.

Code

Code auf Github. Dort werden auch die weiteren möglichen Schreibweisen der NgFor-Direktive gezeigt.

Live Demo auf angular2kochbuch.de

Weitere Ressourcen

Die Performance mit trackBy verbessern

Problem

Ich habe eine große Liste von Objekten, die ich mit NgFor anzeige und ich möchte die Liste durch eine Liste ersetzen, die größtenteils die gleichen Objekte enthält.

Zutaten

Lösung

app.component.ts
 1 import { Component } from '@angular/core';
 2 
 3 interface User {
 4   firstname: string,
 5   lastname: string,
 6   id: number
 7 }
 8 
 9 const users: Array<User> = [
10   {firstname: 'Max', lastname: 'Mustermann', id: 0},
11   {firstname: 'John', lastname: 'Doe', id: 1}
12 ];
13 
14 @Component({
15   selector: 'app-root',
16   template: `
17     <ul>
18       <li *ngFor="let user of users; trackBy:trackById">
19         Name: {{user.firstname}} {{user.lastname}}
20       </li>
21     </ul>
22   `
23 })
24 export class AppComponent {
25   users = users;
26 
27   constructor() {...}
28 
29   trackById(index: number, user: User) {
30     return user.id;
31   }
32 }

Erklärung:

Damit wir “trackBy” effizient nutzen können, müssen die Objekte in unserem Array eine Eigenschaft, deren Wert für jedes Objekt eindeutig ist, besitzen. Wir haben hier eine Eigenschaft namens “id” benutzt.

  • Zeilen 9-12: Array mit User-Objekten die einen eindeutigen Wert für die id-Eigenschaft besitzen
  • Zeile 18: Hier nutzen wir die spezielle Eigenschaft “trackBy” der NgFor-Direktive mit der trackById-Methode der Klasse (siehe Zeilen 29-31)
  • Zeilen 29-31: Methode, die wir in Kombination mit der trackBy-Eigenschaft in Zeile 18 nutzen

Diskussion

Es kann zu Performance-Problemen kommen, wenn wir NgFor mit großen Listen nutzen und wir später die Liste durch eine Neue ersetzen. In solchen Fällen können wir trackBy nutzen. Angular wird dann nur die DOM-Elemente ersetzen, die sich tatsächlich geändert haben. Ohne trackBy muss Angular die komplete Liste im DOM neu generieren, da es nicht wissen kann, dass sich ggf. viele Elemente gar nicht geändert haben.

Damit Angular erkennen kann, welche Elemente sich geändert haben, müssen wir eine trackBy-Methode (hier “trackById”) definieren. Diese erhält den Index und ein Listen-Element als Parameter und gibt den Wert der eindeutigen Eigenschaft (hier “user.id”) zurück. Wenn jetzt die Liste ersetzt wird, wird Angular durch die neue Liste gehen und für jedes Element die trackBy-Methode aufrufen. Falls der zurückgegebene Wert schon bekannt ist (z. B. das Element mit ID 1 war schon in der alten Liste), wird Angular das Element mit dem schon bekannten Element vergleichen. Wenn das alte sich vom neuem Element unterscheidet, wird das DOM aktualisiert. Falls diese gleich sind, bleibt das DOM so wie es ist. Elemente, die noch nicht bekannt sind, werden hinzugefügt und alte Elemente, die sich nicht mehr in der Liste befinden, werden aus dem DOM entfernt.

Das Code-Beispiel auf Github ist ausführlicher als das Beispiel hier. Dort können wir auch sehen, wie sich in jedem Fall das DOM verändert, wenn wir auf den “New List” Button klicken. Am einfachsten ist es, in den Chrome DevTools sich die Elemente im DOM anzuschauen und gleichzeitig auf den Button zu klicken. In den Varianten ohne “trackBy” wird sich die komplette Liste ändern und in den Varianten mit “trackBy” nur das zweite Element der Liste.

Code

Code auf Github. Dort werden auch die weiteren möglichen Schreibweisen der NgFor-Direktive mit trackBy gezeigt.

Live Demo auf angular2kochbuch.de