6–1 Komponente, Template und Bindings im Zusammenspiel
Um diese Bindings zu steuern, nutzen wir die Template-Syntax von Angular, die wir gleich noch genauer betrachten. In den beiden folgenden Storys dieser Iteration gehen wir außerdem gezielt auf die verschiedenen Arten von Bindings ein.
Der Style einer Komponente
Um das Aussehen einer Komponente zu beeinflussen, werden Stylesheets eingesetzt, wie wir sie allgemein aus der Webentwicklung kennen. Neben den reinen Cascading Style Sheets (CSS) können wir auch verschiedene Präprozessoren einsetzen: Sass, Less und Stylus werden direkt unterstützt. Welches Style-Format wir standardmäßig verwenden wollen, können wir auswählen, wenn wir die Anwendung mit ng new erstellen.
Normalerweise verwendet man eine große, globale Style-Datei, die alle gestalterischen Aspekte der Anwendung definiert. Das ist nicht immer schön, denn hier kann man leicht den Überblick verlieren, welche Selektoren wo genau aktiv sind oder womöglich gar nicht mehr benötigt werden. Außerdem widerspricht eine globale Style-Definition dem modularen Prinzip der Komponenten.
Stylesheets von Komponenten sind isoliert.
Angular zeigt hier einen neuen Weg auf und ordnet die Styles direkt den Komponenten zu. Diese direkte Verknüpfung von Styles und Komponenten sorgt dafür, dass die Styles einen begrenzten Gültigkeitsbereich haben und nur in ihrer jeweiligen Komponente gültig sind. Styles von zwei voneinander unabhängigen Komponenten können sich damit nicht gegenseitig beeinflussen, sind bedeutend übersichtlicher und liegen immer direkt am »Ort des Geschehens« vor.
Ein Blick ins Innere: View Encapsulation
Styles werden einer Komponente zugeordnet und wirken damit auch nur auf die Inhalte dieser Komponente. Die Technik dahinter nennt sich View Encapsulation und isoliert den Gültigkeitsbereich eines Anzeigebereichs von anderen. Jedes DOM-Element in einer Komponente erhält automatisch ein zusätzliches Attribut mit einem eindeutigen Bezeichner, siehe Screenshot. Die vom Entwickler festgelegten Styles werden abgeändert, sodass sie nur für dieses Attribut wirken. So funktioniert der Style nur in der Komponente, in der er deklariert wurde. Es gibt noch andere Strategien der View Encapsulation, auf die wir aber hier nicht eingehen wollen.
Angular generiert automatisch Attribute für die View Encapsulation.
Die Styles werden ebenfalls in den Metadaten einer Komponente angegeben. Dafür sind zwei Wege möglich, die wir auch schon von den Templates kennen:
Style-URL: Es wird eine CSS-Datei mit Style-Definitionen eingebunden (styleUrls).
Inline Styles: Die Styles werden direkt in der Komponente definiert (styles).
Im Listing 6–4 werden beide Wege gezeigt. Wichtig ist, dass die Dateien und Styles jeweils als Arrays angelegt werden. Grundsätzlich empfehlen wir Ihnen auch hier, für die Styles eine eigene Datei anzulegen und in der Komponente zu referenzieren. Die Angular CLI unterstützt beide Varianten.
Der herkömmliche Weg zum Einbinden von Styles ist natürlich trotzdem weiter möglich: Wir können globale CSS-Dateien definieren, die in der gesamten Anwendung gelten und nicht nur auf Ebene der Komponenten. Diesen Weg haben wir gewählt, um das Style-Framework Semantic UI einzubinden, siehe Seite 70.
@Component({
styleUrls: ['./my.component.css'],
// ODER
styles: [
'h2 { color:blue }',
'h1 { font-size: 3em }'
],
// [...]
})
export class MyComponent { }
Listing 6–4 Style-Definitionen in Komponenten
6.1.2Komponenten in der Anwendung verwenden
Rule of One
Eine Komponente wird immer in einer eigenen TypeScript-Datei notiert. Dahinter steht das Rule of One: Eine Datei beinhaltet immer genau einen Bestandteil und nicht mehr. Dazu kommen meist ein separates Template, eine Style-Datei und eine Testspezifikation. Diese vier Dateien sollten wir immer gemeinsam in einem eigenen Ordner unterbringen. So wissen wir sofort, welche Dateien zu der Komponente gehören.
Eine Komponente besitzt einen Selektor und wird automatisch an die DOM-Elemente gebunden, die auf diesen Selektor matchen. Das jeweilige Element wird das Host-Element der Komponente. Das Prinzip haben wir einige Seiten zuvor schon beleuchtet.
Komponenten im AppModule registrieren
Damit dieser Mechanismus funktioniert, muss Angular die Komponente allerdings erst kennenlernen. Die reine Existenz einer Komponentendatei reicht nicht aus. Stattdessen müssen wir alle Komponenten der Anwendung im zentralen AppModule registrieren.
Dazu dient die Eigenschaft declarations im Decorator @NgModule(). Hier werden alle Komponenten2 notiert, die zur Anwendung gehören. Damit wir die Typen dort verwenden können, müssen wir alle Komponenten importieren.
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { FooComponent } from './foo/foo.component';
import { BarComponent } from './bar/bar.component';
@NgModule({
declarations: [
AppComponent,
FooComponent,
BarComponent
],
// ...
})
export class AppModule { }
Listing 6–5 Alle Komponenten müssen im AppModule deklariert werden.
6.1.3Template-Syntax
Nachdem wir die Grundlagen von Komponenten kennengelernt haben, tauchen wir nun in die Notation von Templates ein.
Angular erweitert die gewohnte Syntax von HTML mit einer Reihe von leichtgewichtigen Ausdrücken. Damit können wir dynamische Features direkt in den HTML-Templates nutzen: Ausgabe von Daten, Reaktion auf Ereignisse und das Zusammenspiel von mehreren Komponenten mit Bindings.
Wir stellen in diesem Abschnitt die Einzelheiten der Template-Syntax zunächst als Übersicht vor. Im Verlauf des Buchs gehen wir auf die einzelnen Konzepte noch gezielter ein.
{{ Interpolation }}
Ein zentraler Bestandteil der Template-Syntax ist die Interpolation. Hinter diesem etwas sperrigen Begriff verbirgt sich die Möglichkeit, Daten mit zwei geschweiften Klammern in ein Template einzubinden.
Template-Ausdruck Die Daten werden bei der Interpolation automatisch aktualisiert.
Zwischen den