Angular 4: Konzepte und Begriffe

Das Angular-Framework erlaubt uns auf einfach Weise Anwendungen für Web, Mobile oder Desktop zu entwickeln. Ich habe hier eine Übersicht der wichtigsten Konzepte zusammengefasst.

Vorwort

Googles Angular ist ein Framework um Web- und Desktopanwendungen mit TypeScript, HTML und CSS zu entwickeln (sogenannte Single page applications). Momentan gibt es Angular in Version 4.3.0 (Stand Juli 2017).

Angular selbst besteht aus vielen weiteren Modulen (deren Namen beginnen mit @angular). Für die Entwicklung mit Angular gibt es eine breite Auswahl an Tools und Komponenten. Als Entwicklungsumgebung rate ich zu IntelliJ Idea oder Visual Studio Code.

Eine beachtliche Sammlung an Libraries kann man auf devarchy.com finden. Ebenso möchte ich das Bootstrap Framework (bietet Komponenten, CSS-Stylesheet, JavaScript), sowie Material Design (UI Komponenten, Design) empfehlen. Das Clarity Design System bietet ebenso eine große Anzahl an Widgets und Design Guidelines.

Struktur einer Angular-Anwendung

Eine typische Angular-Anwendung teilt sich u.a. in folgende Bestandteile auf:

  • HTML Templates definieren wie Komponenten gerendert werden
  • Komponenten, die diese statischen Templates um Variablen und Methoden erweitern
  • Dienste, die Anwendungslogik (Logging, Konfiguration, Daten, etc.) bereitstellen
  • Module, die die Dienste und Komponenten inhaltlich logisch kapseln

Eine normale Typescriptklasse wird mittels der Annotation (bzw. Decorator) @Component als Angular-Komponente definiert. Dabei verbindet sie die Logik der Klasse mit einem HTML-Template.

Im Browser werden HTML-Konstrukte in den DOM, das Data Object Model, umgewandelt. Verändert man etwas im HTML-Code ändert sich die Seite nicht. Der Nutzer muss zuerst die Seite im Browser aktualisieren. Verändert man jedoch etwas im DOM, aktualisiert sich die Webseitenansicht sofort. Wichtig zu wissen ist, dass Angular den DOM manipuliert.

TypeScript erweitert Javascript um Konzepte wie Typisierung, Klassen und Interfaces. TypeScript kann jedoch nicht direkt von Browsern ausgeführt werden. Deswegen wird es zuerst in JavaScript umgewandelt und kompiliert. Im Unterschied zu JavaScript verwendet TypeScript Strong Typing, d.h. Variablen haben einen definierten Typ.

Angular CLI

Am einfachsten werden neue Komponenten über Angular CLI erstellt. Angular CLI ist eine Kommandozeilenschnittstelle zu Angular.

  • ng new erzeugt ein neues Angular-Projekt
  • ng generate erzeugt Komponenten, Services, uvm.
  • ng serve baut ein Grundgerüst der Applikation
  • ng lint kontrolliert den Code auf die Einhaltung vorgegebener Code Konventionen

Eine Komponente wird zum Beispiel mittels ng g component myComponent erzeugt. Dabei werden praktischerweise direkt die zugehörigen Dateien für CSS, HTML und spec.ts (für die Tests) erstellt. Das neue Modul myComponent.component.ts  wird automatisch im Hauptmodul app.module.ts unter declarations eingebunden (bzw. unter providers wenn es ein Service ist).

Typ Befehl
Component ng g component my-component
Directive ng g directive my-directive
Pipe ng g pipe my-pipe
Service ng g service my-service
Class ng g class my-class
Guard ng g guard my-guard
Interface ng g interface my-interface
Enum ng g enum my-enum
Module ng g module my-module

Der Styleguide von Angular gibt Regeln zur einheitlichen Entwicklung von Angularanwendungen vor. Er definiert wie Klassen, Komponenten und Test zu benennen sind und schlägt vor, nur eine Klasse pro Datei zu definieren. Des Weiteren sind Klassen sinnvollerweise nach bestimmten Richtlinien zu benennen. Ein Service z.B. als myname.service.ts, eine Komponente als myname.component.ts.

@Component-Umgebung

Eine Klasse wird durch den @Component Dekorator um Metadaten erweitert. Dieser Dekorator markiert die Klasse als Angular-Komponente und definiert, wie sie verarbeitet und instantiiert werden soll. Innerhalb der @Component-Umgebung existieren vier wichtige Konzepte:

@Component({
   selector: 'app-my',
   templateUrl:'./my.component.html',
   styleUrls: ['./my.component.scss']
})
export class MyComponent {
  • selector: Dieser CSS-Selektor ermöglicht das Einfügen einer Instanz dieser Komponente in andere HTML-Templates, z.B. <app-my></app-my>
  • templateUrl: Pfad zur HTML-Vorlage der Komponente
  • styleUrls: Pfade zu einem oder zu mehreren CSS-Stylesheets
  • providers: Liste von Services, die mittels Dependency Injection bereitgestellt werden

Binding

Angular bietet verschiedene Wege um Komponenten mit HTML-Templates zu koppeln.

  1. Interpolation binding: Hierbei kann ein String-Attribut value:string mittels {{value}} aus der Komponente an das Template gebunden werden.
  2. Property binding: Von der Component aus wird eine Property mittels [property] ="value" im Template verändert.
  3. Event binding: Events aus dem Template werden zur Component geschickt. Das können etwa Mausklicks (click)="method(var)" oder andere Events sein.
  4. Two-way binding: Hierbei kann mittels Property Binding ein Wert aus der Component eingefügt, als auch mittels Event Binding eine Eingabe aus dem Template in Richtung Component geschickt werden: [(value)]
  5. Attribut binding: Attribute von HTML-Befehlen, wie zum Beispiel <td rowspan={{value}}>, können nicht mittels property binding angesprochen werden. Hier hilft attribut binding mittels <td [attr.rowspan]={{value}}>  aus.
  6. Class binding: Mit diesem Binding können dynamisch CSS Klassenattribute von DOM-Objekten entfernt oder hinzugefügt werden.
  7. Style binding: Dieses Binding erlaubt das dynamische Aktivieren von CSS Styles.

Wenn man auf Strings bindet, hat man oft die Wahl zwischen interpolation und property binding. Hinsichtlich der leichteren Lesbarkeit wählt man in diesem Fall eher interpolation binding.

Structural Directives

Structural directives entfernen, ersetzen, oder fügen Elemente im DOM hinzu. Sie verändern also die Struktur des DOMs. Häufig verwendete structural directives sind *ngIf, *ngFor und ngSwitchCase (mit [ngSwitch] und ngSwitchDefault). Diese werden verwendet um

  • *ngIf: Elemente anzuzeigen/aus dem DOM zu entfernen,
  • *ngFor : Schleifen über Listen durchzuführen, sowie
  • ngSwitch : Fallunterscheidungen abzuwickeln.

In Angular 4 wurde das *ngIf Statement erweitert. Es bietet nun die Möglichkeit einen else-Pfad anzugeben. Sollte also myClass.myAttr definiert bzw. true sein, wird First option angezeigt. Ansonsten wird das Template mit der ID secondOne ausgegeben.

<div *ngIf="item.price; else sold"> {{item.price}} </div>
<ng-template #sold> Out of stock </ng-template>

Mit Hilfe von ngFor können wir über ein Array iterieren und für jedes Element einen HTML-Baustein einfügen. Zum Beispiel können wir einer Liste Einträge hinzufügen:

<ul>
   <li *ngFor="let item of items">{{item.name}} - {{item.price}}</li>
</ul>

Dependency Injection

Mittels Dependency Injection (DI) kann Angular Instanzen (meist Services) in Komponenten einspeisen. Das Ganze wird über den Injector gehandhabt. Definiert man im Wurzelmodul innerhalb der providers: [...] Umgebung die Serviceklassen, können diese per DI später global genutzt werden. Es existiert dabei nur eine Instanz eines jeden Dienstes (Singleton).

Auf Klassenebene wir die Einbindung innerhalb der @Component Umgebung durchgeführt werden. In diesem Fall bekommt jede Komponente eine neue Instanz des Services.

Attribute können mittels @Input() an Attribute anderer Klassen gebunden werden. Dazu muss das Inputsymbol mit import {Input} from ‘@angular/core’; importiert werden.

Asynchrone Aufrufe

Typischerweise kommuniziert die Nutzeroberfläche mit einer Datenhaltungsschicht. Diese wird asynchron angesprochen, wobei die UI währenddessen weiter benutzbar bleiben soll. Hier kommt das Konzept der Promise ins Spiel. Der entfernte Service wird aufgerufen (z.B. per HTTP.GET Request), führt seine Aufgabe asynchron durch und schickt zu einem späteren Zeitpunkt das Ergebnis des Aufrufes zurück. Wir greifen hierfür auf das RxJS Projekt zurück.