Angular. Ferdinand Malcher
Daten können jederzeit kopiert werden (siehe Abschnitt zum Spread-Operator ab Seite 42), ohne dass wir eine falsche Verwendung befürchten müssen.
Das Datenmodell ist kompatibel bzw. »bereit« für den Einsatz von NgRx/Redux, denn wir werden dort die Objekte mehrfach mit dem Spread-Operator kopieren (siehe Kapitel zu Redux ab Seite 607).
Führende Codegeneratoren wie swagger-codegen, appollo-codegen usw. (siehe Kasten im Kapitel zu RxJS und HTTP auf Seite 239) generieren standardmäßig Interfaces und keine Klassen.
Zwei Interfaces mit der gleichen Signatur sind miteinander kompatibel und untereinander austauschbar. Zwei unterschiedliche Klassen mit der gleichen Signatur kann man hingegen nicht untereinander austauschen, dies verhindert bereits der Compiler. In großen Projekten kann diese Tatsache relevant werden, vor allem dann, wenn man Module getrennt voneinander entwickelt.
Diese Punkte, vor allem die Kompatibilität mit der Redux-Architektur, haben uns zu unserer Entscheidung bewegt. Wenn Sie Ihr eigenes Projekt planen, so möchten wir Ihnen dazu raten, ebenso die Entscheidung zwischen Klassen oder Interfaces rechtzeitig zu fällen. Eine späte Änderung kann sonst viel Aufwand bedeuten.
Interfaces für die Datenmodelle anlegen
Interfaces für Buch und Thumbnail
Es bietet sich an, für die beiden Entitäten ein Interface zu erstellen, das die obligatorischen und optionalen Attribute beschreibt. Diese Interfaces sollen in einer Datei in dem gemeinsamen Ordner
$ ng g interface shared/book
Listing 6–12 Interface Book anlegen mit der Angular CLI
Der Befehl verlangt als Argument den Namen und Pfad der neuen Klasse. Der Ordner
Das erzeugte Interface befüllen wir nun mit den zuvor festgelegten Eigenschaften unseres Buchs. Optionale Eigenschaften werden dabei durch ein nachgestelltes ?-Symbol gekennzeichnet. Wir legen in der gleichen Datei ebenso noch das Interface Thumbnail an und verweisen darauf im Interface Book. Da wir das Interface für die Vorschaubilder im weiteren Verlauf auch separat aus anderen Komponenten und Services heraus verwenden wollen, exportieren wir es ebenso wie das Interface Book.
export interface Book {
isbn: string;
title: string;
authors: string[];
published: Date;
subtitle?: string;
rating?: number;
thumbnails?: Thumbnail[];
description?: string;
}
export interface Thumbnail {
url: string;
title?: string;
}
Listing 6–13 Das Interface Book (book.ts)
Wir haben eine neue Datei für die beiden Interfaces angelegt, und unser Projekt sollte jetzt die folgende Ordnerstruktur besitzen:
Eine Komponente für die Buchliste
Jetzt, da die Grundlage für die Bücher geschaffen ist, wollen wir unsere Buchliste angehen. Die Anwendung verfügt bereits über eine Hauptkomponente. Zusätzlich dazu wollen wir nun eine weitere Komponente anlegen, die nur die Buchliste beinhaltet. Das ist sinnvoll, weil die Buchliste ein abgrenzbarer Bereich der Anwendung ist. Solche Teile sollten Sie auch immer in eigenen Komponenten unterbringen. Das erhöht die Wiederverwendbarkeit und Wartbarkeit, nicht zuletzt fürs Testing.6
Wir wählen für die neue Komponente den Namen BookList-Component und führen das folgende Kommando mit der Angular CLI aus, um die Komponente zu erzeugen (ausgehend vom Hauptverzeichnis der Anwendung):
$ ng g component book-list
Listing 6–14 Komponente BookListComponent mit der Angular CLI anlegen
Die Angular CLI legt für jede Komponente automatisch einen neuen Ordner an, in dem die Komponentenklasse, das zugehörige Template, ein Stylesheet und eine Testspezifikation untergebracht sind. Zu dem Klassennamen wird automatisch das Suffix Component hinzugefügt! Diese Konvention entspricht dem Angular-Styleguide.7
Wir erhalten die folgende Ordnerstruktur:
Die Angular CLI hält die Namenskonvention ein.
Es fällt positiv auf, dass sich die Angular CLI an die Namenskonventionen aus dem Styleguide hält (siehe Kasten). Die Klasse heißt nun
Namenskonventionen in Angular – dashed-case vs. CamelCase
In Angular wird eine strenge Namenskonvention verfolgt. Es werden grundsätzlich zwei verschiedene Formate genutzt:
dashed-case: Diese Konvention wird für Dateinamen und Selektoren genutzt. Eine alternative Bezeichnung ist kebab-case.
CamelCase: Die CamelCase-Konvention wird für die Namensgebung von Klassen und Interfaces verwendet.
Entsprechend der Zielsetzung der ersten Iteration soll die Komponente eine Listenansicht von Büchern darstellen. Hierzu passen wir zunächst das generierte Template an. Wir legen das Grundgerüst für die Liste an und greifen dafür auf die Elemente des Style-Frameworks Semantic UI zurück.
ngFor für die Buchliste
Schließlich verwenden wir die Direktive ngFor, um durch die Liste der Bücher zu iterieren. ngFor wiederholt in unserem Fall das Element <a class="item"> und dessen Inhalte für jedes Buch. In jedem dieser Blöcke werden der Titel, die Autoren und die ISBN des Buchs ausgegeben. Der Untertitel ist optional und wird mit der Direktive ngIf nur eingeblendet, sofern dieser angegeben wurde. Wir verwenden die Interpolation, um Propertys der Komponentenklasse im Template auszugeben.
Autoren anzeigen mit ngFor
Die Liste der Autoren soll kommasepariert angezeigt werden. Wir verwenden hier ebenfalls ngFor und durchlaufen die Liste der Autoren. Um nach dem letzten Element kein Komma anzuzeigen, machen wir uns die Hilfsvariablen der Direktive zunutze: Die Variable last ist true, sobald die Schleife das letzte Element des Arrays erreicht hat. Wir können diesen Wert in eine lokale Variable l speichern und damit feststellen, wann der letzte Name ausgegeben wurde. Das