Angular, wiederverwendbare Komponenten Teil 1/2

Komponenten sind das zentrale Konzept im Universum von Angular. Eine Komponente zu schreiben ist hier nicht schwer, die Herausforderung besteht in aller Regel darin Komponenten zu schaffen die möglichst viel Funktionalität so  kapseln das sie anderer Stelle wieder verwendet werde kann, dem „Nutzer“ aber den Freiraum lässt je nach Situation Anpassungen vornehmen zu können. Dieser Beitrag beschäftigt sich mit all den Möglichkeiten die Angular in diesem Kontext bietet.

ng-Content

Eine der leichteren Anforderungen ist es einen Bereich innerhalb der eigenen Komponente an zu bieten, in dem der Verwender eigene Inhalte platzieren kann. Ein typisches Beispiel wäre hier eine Layout-Komponete die einen bestimmten Rahmen vorgibt. Hierfür bietet Angular „ng-content“:

box-component.html

<div> <ng-content></ng-content></div>
<div> <ng-content select="[appBoxHeader]"></ng-content></div>
<div> <ng-content select=".footer"></ng-content></div>

In diesem Beispiel bietet die Komponente 3 Stellen an denen der Verwendet beliebige Inhalt einfügen kann. Die eindeutig Identifikation der Stellen wird durch Selektoren bewerkstelligt. In diesem Beispiel verwenden wir (von oben nach unten) eine Default-Stelle, eine Selektion über eine Direktive und eine Selektion über eine CSS-Klasse.

Die Verwendung dazu könnte wie folgt aussehen:

insert-children.component.html

  <app-box>
    <span>Hello Nr. 1</span>
    <span appBoxHeader>Hello Nr. 2</span>
    <span class="footer">Hello Nr. 3</span>
  </app-box>

ngTemplateOutlet

Einen Schritt weiter geht die Verwendung des ngTemplateOutlet. Hier können wir dem Anwender, auf Basis von HTML5 Templates, die optionale Möglichkeit geben bestimmte Teile unserer Komponente aus zu tauschen. Im folgenden Beispiel geht es darum eine sehr einfache Layout Komponente an zu bieten, die OutOfTheBox verwendet werden kann. Zusätzlich wollen wir dem Verwendet aber die Möglichkeit geben bei Bedarf bestimmte Teile mit eigenen Inhalten aus zu tauschen.

box-with-default.component.html

<div class="footer">
    <ng-template [ngTemplateOutlet]="footerTemplate"></ng-template>

© by GEDOPLAN, Dominik Mathmann</div>

Im Footer-Bereich unserer Komponente wollen wir eine standardisierte Copyright Information anzeigen, falls der Verwender keine eigenen Inhalte anbietet. In unserer Komponente sehen  wir dafür einen Bereich mittels „ng-template“ vor. Falls dieser Bereich vom Benutzer nicht mit „Leben gefüllt“ wird zeigen wir einen Standard-Text an. Sollte der Verwender ein entsprechendes Template übergeben sorgt die Direktive ngTemplateOutlet dafür das diese an der Stelle angezeigt wird. Die Referenz auf das individuelle Template (footerTemplate) lassen wir uns zu diesem Zweck in den Controller unserer Komponente injizieren:

box-with-default.component.ts

  @ContentChild("footer")
  footerTemplate: TemplateRef<any>;

Verwendung:

  <app-box-with-default title="Hello-Box">
       ...
       <ng-template #footer>
        <i>...my special footer...</i>
      </ng-template>
  </app-box-with-default>

Solche dynamischen Template-Bereiche können natürlich mehrfach in unserer Komponente vorkommen. Die Verknüpfung zwischen der Position innerhalb unserer Komponente und dem vom Verwender bereitgestellten Template geschieht über die Verwendung einer übereinstimmenden Template Variable (#footer > @ContentChild („footer“))

ngTemplateRef

Neben dem Austausch von festgelegten Template-Bereichen über TemplateRef gibt es auch Anwendungsfälle in denen wir innerhalb unserer Komponente eine Iteration durchführen wollen. Hier ist eine logische Anforderung, dass wir das Template der Iteration übergeben wollen, natürlich mit entsprechener Möglichkeit auf das aktuelle Objekt der Iteration zugreifen zu können.

entries.box.component.html

<div *ngIf="userTemplate">
  <ng-template ngFor [ngForOf]="elements" [ngForTemplate]="userTemplate">
  </ng-template></div>

Verwendung findet hier wieder das bereits bekannte ng-template mit einer vorrangestellten (optionalen) Prüfung ob einer individuelles Template überhaupt übergeben wurde. Die dann folgende Syntax mag auf den ersten Blick Verwirrend erscheinen. Hier wird ein Template verwendet, mit einer Direktive (ngFor) versehen um die Iteration zu ermöglichen. Mittels Property-Binding werden die Elemente definiert ([ngForOf]] und eine Lauf-Variable für das Element festgelegt (let-e). Diese Möglichkeit verwenden wir sehr oft, nur das Angular uns dafür mit seiner Microsyntax eine etwas einfachere Schreibweise anbietet. So entspricht die Verwendung von *ngFor beispielsweise im Hintergrund exakt dieser Synatx. So sind folgende Schreibweisen funktional völlig identisch:

	<li *ngFor="let e of entries"> Entry: {{e}}</li>
...
    <ng-template ngFor [ngForOf]="entries" let-e>
	<li>Entry: {{e}}</li>
</ng-template>

Die Verwendung der oben gezeigten Komponente ist dann wieder naheliegender:

Verwendung

  <ng-template let-entry>
<ul>
	<li><a (click)='alert(entry)'>{{entry.title}}</a></li>
</ul>
</ng-template>

Lediglich die Defintion der Laufvariablen mittels let-entry ist im Gegensatz zum vorrangegangenen Beispiel neu und dient logischerweise dazu Zugriff auf das aktuelle Iterationsobjekt zu bekommen.

Wie wir im ersten Teil sehen konnten bietet Angular mächtige Möglichkeiten Komponenten wiederverwenbar UND individualisierbar zu machen. Im zweiten Teil tauchen wir noch ein Stück tiefer und werfen einen Blick auf das dynamische Hinzufügen von Komponente mittels ViewContainerRef, ComponentFactory und ComponentFactoryResolver.

Beispiele zum kompletten nachlesen wie immer:

github.com/GEDOPLAN

Advertisements

Über Dominik Mathmann
Dominik Mathmann arbeitet als Berater, Entwickler und Trainer bei der GEDOPLAN GmbH. Auf Basis seiner langjährigen Erfahrung in der Implementierung von Java-EE-Anwendungen leitet er Seminare, hält Vorträge und unterstützt Kunden bei der Konzeption und Realisierung von Webanwendungen vom Backend bis zum Frontend. Sein derzeitiger Schwerpunkt liegt dabei auf der Entwicklung von JSF-Anwendungen. Er sieht die stärker werdende Position von JavaScript-Frameworks jedoch positiv und beschäftigt sich darüber hinaus mit Webframeworks wie AngularJS.

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s

%d Bloggern gefällt das: