German version of my talk. A quick dive into the elements of angular. Find example source code and a lot of explanations on modules, components and services.
Es ist Open Source und wird auf GitHub maintained. Das Projekt selbst ist in mehrere Module unterteilt, sodass man lediglich die Module laden muss, die für einen selbst relevant sind. Alle Module werden parallel entwickelt und wiesen die gleiche Versionsnummer auf. Angular setzt mittlerweile auf Semantic Versioning. Es gibt zweimal im Jahr ein neues Major-Release
ein Typsystem für JavaScript einzusetzen. Ursprünglich wurde mit AtScript eine eigene Lösung entwickelt. Während der Entwicklung wurde auf TypeScript geschwenkt. TypeScript bietet statische Typenprüfung, die Verwendung von Interfaces und einen Transpiler der moderne JavaScript- Features auch für ältere Browser verfügbar macht.
um, das vom Browser ausgeführt wird. Eine TypeScript-Datei endet per Konvention auf .ts. Dem Compiler können über eine Konfigurationsdatei (tsconfig.json) bestimmte Einstellungen mitgegeben werden. Liegt einen Bibliothek nicht in TypeScript vor, können Typdefinitionen heruntergeladen und installiert werden (http:// definitelytyped.org/)
wie möglich zu machen, gibt es das Angular-CLI-Tool. Dieses Werkzeug kommt im gesamten Lebenszyklus zum Einsatz von der Erstellung des Projekts, über die Entwicklung des Quellcodes bis zum Bau der fertigen Applikation für den Produktivbetrieb.
des DOM aus. Sie kommen in den Templates einer Applikation vor. Eine Component ist eine Sonderform der Directive, da sie ein eigenes Template aufweist.
gibt an, welche weiteren Module importiert werden, welche Components und Services verfügbar sind und welche Component die Wurzel der Applikation bildet. Das App Module wird initial vom CLI erzeugt
mit folgendem Inhalt erzeugt: src/app/hello-world/ ├── hello-world.component.css ├── hello-world.component.html ├── hello-world.component.spec.ts └── hello-world.component.ts Die Component wird automatisch im Module registriert
benötigten Dateien • Decorator mit Metadaten der Component • Component Class Der Selector gibt den Tag-Namen an über den die Component eingebunden wird. Die Component-Klasse dient der Datenhaltung für das Template und stellt Methoden zur Verfügung.
für die Component. Diese Lösung wird durch das Umbenennen der CSS-Klassen gelöst. Über die encapsulation-Eigenschaft des Decorators können auch andere Modi verwendet werden: • Native: Der Shadow-DOM wird verwendet • Emulated: CSS Renaming (Standard) • None: Keine Kapselung, Styles gelten global
im Decorator einer Component definiert werden oder in einer separaten HTML-Datei, was die Empfohlene Lösung ist. Per Interpolation ({{}}) kann vom Template aus auf die Eigenschaften der Component-Klasse zugegriffen werden.
Component-Class zugegriffen werden. (click)=“handleClick()” Mit dem Event-Binding wird beim Auslösen des Events z.B. eines Klicks die verbundene Methode der Component-Class aufgerufen. Dieser Methode können Eigenschaften übergeben werden. Mit der $event-Variablen erhält die Methode eine Referenz auf das Event-Objekt.
jede dieser Phasen gibt es einen Hook, für den man eine Funktion definieren kann. Vorgehensweise: • Interface implementieren • Hook-Methode umsetzen import { Component, OnInit } from '@angular/core'; @Component({…}) export class ListComponent implements OnInit { ngOnInit() { // initialization here } }
Initialisierung (wird nur 1x aufgerufen) Wird bei der Change Detection aufgerufen Nachdem externer Inhalt verarbeitet wurde Reaktionsmöglichkeit auf Inhaltsprüfungen Reaktionsmöglichkeit auf Initialisierung Hook nach View und View Children Wird vor der Zerstörung aufgerufen
In einem Template einer Component können beliebig viele Child Components referenziert werden. Diese Art der Strukturierung erhöht die Wiederverwendbarkeit einzelner Teile der Appliktion. Außerdem wird durch definierte Schnittstellen eine lose Kopplung zwischen den einzelnen Components geschaffen.
hinein zu reichen, wird das Angular Property Binding ([]) in Verbindung mit Input Binding (@Input) verwendet. Achtung: auf @Input folgen immer Klammern. <ul> <app-list-item *ngFor="let item of items" [item]="item"> </app-list-item> </ul> @Component({…}) export class ListItemComponent { @Input() private item: Item; constructor() { } }
eine Child Component hineingegeben werden, sollten nicht by Reference verändert werden. Werden die Daten angepasst, passiert dies auf einer Kopie der Daten und die Parent Component wird per Event benachrichtigt. 1. Output Binding festlegen 2. Eventhandler erzeugen und emit-Methode aufrufen 3. In der Eltern Component auf das Event reagieren Der Zugriff auf die Event-Daten erfolgt über die $event- Variable
Datenstreams mit Eingabe, Ausgabe und Parametern. Mit den Parametern kann das Verhalten der Pipe beeinflusst werden. Eine Pipe wird durch das | vom Eingangswert getrennt. Die Parameter werden durch Doppelpunkte getrennt. Mehrere Pipes können miteinander verkettet werden. Sie werden ebenfalls durch das |-Zeichen voneinander getrennt. Die Ausgabe einer Pipe dient dann als Eingabe für die nachfolgende.
des Observer-Patterns darstellen. Damit wird asynchrone Programmierung über definierte Schnittstellen möglich. Reactive Extensions sind wesentlich flexibler als Callback-Funktionen und Promises. Reactive Extensions wurden von Microsoft entwickelt und sind für viele Sprachen wie Java, C#, C++ oder JavaScript verfügbar.
Dieser muss anschließend noch als Provider registriert werden. Hierfür gibt es zwei Möglichkeiten: • Am Modul: Das gesamte Modul (app.module.ts unter dem Schlüssel provider) teilt sich eine Instanz des Services • An einer bestimmten Component: Eine Instanz pro Component (Component-Datei im @Component-Decorator als provider)
zunächst geladen werden. Dies geschieht über die Dependency Injection von Angular. Im einfachsten Fall werden die Abhängigkeiten zu anderen Elementen der Applikation im Konstruktor einer Klasse angegeben. Angular sucht daraufhin nach einem passenden Provider und liefert entweder eine bestehende Instanz aus dem Cache aus oder erzeugt eine neue Instanz.
Frameworks. Er dient der Kommunikation mit einem Webserver und kann per Dependency Injection sowohl von anderen Services als auch direkt in Components verwendet werden. 1. HttpModule in app.module.ts als imports einbinden (@angular/http) - wird von der CLI automatisch gemacht 2. HttpService per Dependency Injection laden 3. Instanz verwenden.
RxJS-Observable zurück. Bei diesem Objekt handelt es sich um einen asynchronen Datenstrom auf den verschiedene Operatoren wie z.B. map angewendet werden können. Mit der subscribe-Methode können Sie eine Callback-Funktion registrieren.
proxy-Option von Webpack eingesetzt werden, um Anfragen an den Server auf einen anderen Port umzuleiten. Damit kann ein Backend an die, sich im Entwicklungsbetrieb befindende, Applikation angeschlossen werden, ohne dass Anpassungen am Quellcode erforderlich sind.
internen Datenstruktur. Der Store wird nicht direkt sondern über eine definierte API modifiziert. Meist ist der Store mit dem HTTP- Service verbunden. Der Store selbst ist als Service umgesetzt, der in Components per Dependency Injection eingebunden wird. Die API verfügt meist über Methoden für CRUD-Operationen.
werden Veränderungen über das BehaviorSubject publiziert. Im internen dataStore werden die Daten vorgehalten. In das BehaviorSubject können sowohl Daten geschrieben werden als auch gelesen werden. Außerdem kann es als Observable exportiert werden.
auf dem Store laufen immer nach dem gleichen Schema ab: Zuerst wird der lokale DataStore modifiziert, danach die next-Methode des BehaviorSubjects mit einem Klon des DataStores aufgerufen.
Forms und Reactive Forms. Template Driven Forms sind einfacher und basieren hauptsächlich auf Templates. Reactive Forms sind flexibler und erfordern mehr TypeScript-Quellcode.
[(ngModel)]="model.name" name="name"> Das id-Attribut wird zur Verknüpfung mit dem label verwendet. Das name-Attribut und die ngModel-Direktive dienen der Formularbehandlung durch Angular. Das required-Attribut ist eine Direktive, die einen Validator aktiviert. Durch ngModel werden die Werte direkt mit dem Model der Component synchronisiert.
ng-untouched Wert hat sich geändert ng-dirty ng-pristine Wert ist gültig ng-valid ng-invalid Auf den Status eines Form-Elements kann zugegriffen werden. Angular trackt verschiedene States als CSS-Klassen. Damit können Styles angewendet werden.
required </div> Über den Namen des Eingabefeldes kann auch auf dessen Status zugegriffen werden und so z.B. Fehlermeldungen ein- beziehungsweise ausgeblendet werden.
werden. Diese wird direkt an das Formular gebunden. Sobald das Formular über den Submit-Button abgesendet wird, wird die onSubmit-Methode der Component aufgerufen. Durch das disabled-Attribut wird der Submit-Button erst verfügbar, sobald das Formular valide ist. <form (ngSubmit)="onSubmit()" #addressForm="ngForm"> … <button type="submit" class="btn btn-success" [disabled]="! addressForm.form.valid">Submit</button> </form>
in Ihrem Root-Module das ReactiveFormsModule einbinden (per Imports). Danach erzeugen Sie in Ihrem Template die Struktur. Die Verbindung zum Formular erfolgt hier über die formControlName-Direktive. Alles Weitere geschieht im Code der Component. Hier verwenden Sie den FormBuilder, um das Formular zu erzeugen.
über URLs. Eine Änderung der URL sorgt dabei nicht für einen Page Load, sodass der State der Applikation erhalten bleibt. Angular verfügt über ein eigenes Modul zu diesem Zweck: den Angular Router. Dieses Modul wird standardmäßig von der Angular CLI mit installiert.
wird ein anderer Component-Baum angezeigt. Mit dem RouterOutlet geben Sie an, wo diese Components angezeigt werden sollen. <router-outlet></router-outlet>