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
- Liste von Daten anzeigen
- Anpassungen in der app.component.ts-Datei
Lösung
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
- Weitere Informationen zu lokalen Variablen und Template-Ausdrücken gibt es in Appendix A: Template-Syntax
Gerade und ungerade ngFor-Elemente unterscheiden
Problem
Ich möchte, dass gerade Elemente meiner Liste eine andere Farbe als ungerade erhalten.
Zutaten
- Liste von Daten anzeigen
- Anpassungen in der app.component.ts-Datei, die im Rezept “Liste von Daten anzeigen” verwendet wird
- CSS-Klasse dynamisch setzen, um die CSS-Klasse mit der richtigen Farbe zu setzen
Lösung
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
- Weitere Informationen zu lokalen Variablen gibt es in Appendix A: Template-Syntax
Das erste und das letzte ngFor-Element finden
Problem
Ich möchte das erste und das letzte Element meiner Liste farblich hervorheben.
Zutaten
- Liste von Daten anzeigen
- Anpassungen in der app.component.ts-Datei, die in “Liste von Daten anzeigen” verwendet wird
- CSS-Klasse dynamisch setzen, um die CSS-Klasse mit der richtigen Farbe zu setzen
Lösung
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
- Weitere Informationen zu lokalen Variablen gibt es in Appendix A: Template-Syntax
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
- Liste von Daten anzeigen
- Anpassungen in der app.component.ts-Datei
Lösung
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