Tutorial: Wie man die neuen Pipes in Angular 2 richtig nutzt.

Angular Pro-Tipps: #1 – Angular Pipes

Aaron Czichon

 

Das Angular 2 Release steht vor der Tür – höchste Zeit also, sich mit den neuen Features vertraut zu machen. Mit diesem Beitrag startet auf JAXenter eine neue Reihe, in der uns Web-Experten ihre persönlichen Tipps zur Arbeit mit Angular 2 verraten. Im ersten Teil zeigt Aaron Czichon, wie man die neuen Pipes in Angular 2 richtig nutzt.

Pro-Tipp #1: Angular Pipes

czichon_aaronAngular 2 ist ein Framework voll mit neuen Konzepten und tollen Funktionen. Neben den Components, Provider und vielen weiteren neuen Features gibt es auch die sogenannten Pipes. Dieses Konzept finde ich sehr spannend, weshalb sie auch eines meiner persönlichen Highlights von Angular 2 sind.

Angular Pro-Tipps von Aaron Czichon

In AngularJS (1) gibt es das Filter-Konzept, das den Pipes in Angular 2 sehr ähnlich ist. Angular Pipes ermöglichen es, Daten vor dem Rendering im DOM zu transformieren und/oder zu formatieren (etwa bei Strings). Oftmals möchte man mit Blick auf die User Experience die Daten innerhalb einer App nicht eins zu eins auch in der View darstellen. Stellen wir uns vor, wir bekommen von unserem API ein User-Objekt, das ein JavaScript-Date als JSON-String liefert. In etwa so:

let user = {
    "name": "Aaron Czichon",
    "last_login": "2016-07-07T18:25:43.511Z"
}

Das JSON-Objekt wandeln wir in ein JavaScript-Objekt um und wollen nun dem Benutzer in der View das Datum und die Uhrzeit seines letzten Logins anzeigen. Dazu benötigen wir zunächst die passende View und eine entprechende Komponente.

user-data.html:

<!-- user-data.html -->

<div style="display: flex; justify-content: space-around;">
    <div id="name"></div>
    <div id="lastLogin"></div>
</div>
// userData.component.ts 

import { Component } from '@angular/core';

@Component({
  selector: 'user-data',
  templateUrl: 'user-data.html'
})
export class UserDataComponent {
    let user = {
        name: 'Aaron Czichon',
        last_login: new Date('2016-07-07T18:25:43.511Z')
    }
}

Um nun die User-Daten an die View zu binden, nutzen wir, wie bereits in AngularJS, Interpolation:

<!-- user-data.html -->

<div style="display: flex; justify-content: space-around;">
    <div id="name">{{user.name}}</div>
    <div id="lastLogin">{{user.last_login}}</div>
</div>

Da die Interpolation in diesem Fall bei user.last_login nun die toString()-Methode nutzt und das Ergebnis davon in die View rendert, wird in das UI folgendes gerendert:

// Output  
  
Aaron Czichon               Thu Jul 07 2016 20:25:43 GMT+0200 (Central Europe Daylight Time)

Unsere Nutzer interessieren sich aber weder für die aktuelle Zeitzone, noch dafür, um welchen Wochentag es sich handelt. Wir möchten ihm also nur das Datum und die Uhrzeit anzeigen lassen. Um diese Formatierung möglichst elegant umzusetzen, gibt es in Angular 2 die Möglichkeit, dafür Pipes zu nutzen. Man wendet dabei bei der Interpolation eine Art Filter an, der dann das Ergebnis liefert. Dazu benötigen wir eine neue TypeScript-Klasse, die mit einem Decorator als Pipe deklariert wird:

// loginTimeFormat.pipe.ts

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'loginTimeFormat'})
export class LoginTimeFormatPipe implements PipeTransform {
  transform(value: Date): string {
      let dd = value.getDate();
      let MM = value.getMonth() + 1;
      let yyyy = value.getFullYear();
      let hh = value.getHours();
      let mm = value.getMinutes();

      let formattedDayTime = `${dd}.${MM}.${yyyy} ${hh}:${mm} Uhr`;
      return formattedDayTime;
  }
}

Nun müssen wir die Pipe noch mit unserer UserDataComponent bekannt machen:

// userData.component.ts 

import { Component } from '@angular/core';
import {LoginTimeFormatPipe} from 'loginTimeFormat.pipe';

@Component({
  selector: 'user-data',
  templateUrl: 'user-data.html',
  pipe: [LoginTimeFormatPipe]
})
export class UserDataComponent {
    let user = {
        name: 'Aaron Czichon',
        last_login: new Date('2016-07-07T18:25:43.511Z')
    }
}

Unsere Komponente wurde nun damit bekannt gemacht, dass es eine Pipe mit dem Namen LoginTimeFormatPipe gibt, die auf das Schlüsselwort loginTimeFormat hört. Jetzt müssen wir die Pipe noch zur Anwendung bringen. Um eine Pipe zu nutzen, benötigen wir den sogenannten Pipe-Operator ( | ), der in AngularJS früher für Filter genutzt wurde.

<!-- user-data.html -->

<div style="display: flex; justify-content: space-around;">
   <div id="name">{{user.name}}</div>
   <div id="lastLogin">{{user.last_login | loginTimeFormat}}</div>
</div>

Das Ergebnis wird dann wie erwartet formatiert und in unserer View angezeigt:

// Output  
  
Aaron Czichon               7.7.2016 20:25 Uhr

Um die Formatierung bzw. den Rückgabewert einer Pipe noch spezifischer definieren zu können, kann man die Pipes auch mit Parametern versehen. Wollen wir zum Beispiel das Datum optional gestalten und standardmäßig nur die Uhrzeit ausgeben, müssen wir zunächst unsere Pipe etwas erweitern.

// loginTimeFormat.pipe.ts 

import { Pipe, PipeTransform } from '@angular/core';
@Pipe({name: 'loginTimeFormat'})
export class LoginTimeFormatPipe implements PipeTransform {
  transform(value: Date, includeDate:boolean = false): string {
      let dd = value.getDate();
      let MM = value.getMonth();
      let yyyy = value.getFullYear();
      let hh = value.getHours();
      let mm = value.getMinutes();

      if(includeDate)
        return `${dd}.${MM}.${yyyy} ${hh}:${mm} Uhr`;

      return `${hh}:${mm} Uhr`;
  }
}

Wenn wir nun unser Template unverändert lassen, wird nur noch die Uhrzeit ausgegeben:

// Output  
  
Aaron Czichon               20:25 Uhr

Ändern wir aber unser Template ein wenig ab und geben als Parameter ein true mit, wird das Datum wieder mit ausgegeben.

<!-- user-data.html -->

<div style="display: flex; justify-content: space-around;">
   <div id="name">{{user.name}}</div>
   <div id="lastLogin">{{user.last_login | loginTimeFormat:true}}</div>
</div>
// Output  
  
Aaron Czichon               7.7.2016 20:25 Uhr

Ein weiterer Vorteil der Formatierung mit Pipes ist, dass mehrere Pipes in eine Chain (dt. Kette) geschaltet werden können. Es können also mehrere Pipes auf eine Interpolation angewendet werden. Ein kleines Beispiel dazu:

<!-- user-data.html -->

<div style="display: flex; justify-content: space-around;">
   <div id="name">{{user.name}}</div>
   <div id="lastLogin">{{user.last_login | loginTimeFormat:true | uppercase}}</div>
</div>

Was nun passiert:

  1. Unser user.last_login wird in die LoginTimeFormat-Pipe gesteckt und dort formatiert. Das Datum wird dabei mit ausgegeben.
  2. Das Ergebnis aus der LoginTimeFormat-Pipe wird in die uppercase-Pipe gesteckt.
  3. Das Ergebnis aus dieser Pipe wird im DOM gerendert.
// Output  
  
Aaron Czichon               7.7.2016 20:25 UHR

Angular 2 verfügt über einige Standard-Pipes, die out of the Box genutzt werden können. Dazu zählt in etwa die uppercase-Pipe, die wir im Beispiel oben genutzt haben.

Um Probleme mit undefined– und/oder Null-Exceptions zu verhindern, gibt es den Safe Navigation Operator. Diesen kann man einsetzen, wenn man sich nicht sicher ist, ob das Property, das gebunden wird, nicht zu einem Objekt gehört, das zum Zeitpunkt des Renderns noch undefined und/oder null ist. In unserem Beispiel sieht das so aus:

<!-- user-data.html -->

<div style="display: flex; justify-content: space-around;">
   <div id="name">{{user?.name}}</div>
   <div id="lastLogin">{{user?.last_login | loginTimeFormat:true | uppercase}}</div>
</div>
International JavaScript Conference
Hans-Christian Otto

Testing React Applications

by Hans-Christian Otto (Suora GmbH)

Sebastian Witalec

Building a Robo-Army with Angular

by Sebastian Witalec (Progress)

API Summit 2018
Christian Schwendtner

GraphQL – A query language for your API

mit Christian Schwendtner (PROGRAMMIERFABRIK)

Async-Pipes

Ein letztes Feature der Angular Pipes, das ich kurz erklären möchte, sind die sogenannten Async-Pipes. Mit Async-Pipes ist es möglich, Werte, die asynchron geladen werden, direkt an die View zu binden. Das ist vor allem bei Daten, die von Observables und Promises kommen, sehr nützlich. Das nachfolgende Beispiel veranschaulicht die Funktionsweise:

// AsyncPipeTest.component.ts 

import { Component } from '@angular/core';

@Component({
  selector: 'async-test',
  templateUrl: 'async-pipe-test.html'
})
export class AsyncPipeTestComponent {
    promise: Promise;
    constructor() {
        this.promise = new Promise(function(resolve, reject) {
            setTimeout(function() {
                resolve('Pipe Value from Promise rendered!');
            }, 2000);
        });
    }
}
<!-- async-pipe-test.html -->

<p>{{ promise | async}}</p>

Das Ergebnis:

// Output  
  
Pipe Value from Promise rendered!

Fazit

Pipes ersetzen quasi die Filter aus AngularJS und haben viele der Funktionen übernommen sowie neue Funktion hinzubekommen (wie etwa die Async-Pipes). Pipes ermöglichen es auf einfache Weise, Daten vor deren Anzeige zu transformieren und/oder zu formatieren. Es gibt einige Standard-Pipes, die out of the Box genutzt werden können. Benötigt man eine spezielle Formatierung oder Verarbeitung, können eigene Pipes geschrieben werden. Um Daten asynchron in der View darzustellen, kann die Async-Pipe genutzt werden.

Hier noch eine Liste der Standard-Pipes, die Angular 2 von Haus aus mitliefert:

  • currency
  • date
  • uppercase
  • lowercase
  • json
  • limitTo
  • async
  • decimal
  • percent
Geschrieben von
Aaron Czichon
Aaron Czichon
Aaron Czichon hat im Alter von 14 Jahren mit Software-Entwicklung angefangen und sich PHP und HTML beigebracht. Seit seiner Ausbildung zum Fachinformatiker Anwendungsentwicklung arbeitet er hauptberuflich bei der cellent AG mit Hauptsitz in Stuttgart. Dort ist er als Software-Entwickler im Projektumfeld mit Javascript und .NET tätig. Nebenberuflich ist er als freier Entwickler mit seiner WebAtlas GbR unterwegs und macht seinen IT-Fachwirt um seine Kompetenzen in Unternehmensführung und BWL zu erweitern. Mit Ionic beschäftigt er sich seit dem Erscheinen der 3. Alpha-Version Ende November 2013. Ende 2014 gründete er die deutsche Ionic Community „Ionic Germany“. Er ist Mitglied der Ionic Alpha-Gruppe, welche die aktuellsten Neuerungen und Tools von Ionic zum Testen erhält. Nebenbei ist er auf Konferenzen als Speaker. Dort referiert er überwiegend über das Ionic Framework.
Kommentare

Hinterlasse einen Kommentar

1 Kommentar auf "Angular Pro-Tipps: #1 – Angular Pipes"

avatar
400
  Subscribe  
Benachrichtige mich zu:
Marc
Gast

Danke für den schönen Artikel!

Einen kleinen Fix würde ich allerdings vorschlagen: let MM = value.getMonth() + 1;