Tutorial: Wie man mit dem neuen HTTP-Client Daten lädt und speichert

Angular Pro-Tipps: #2 – HTTP-Client

Angular Pro-Tipps: #2 – HTTP-Client

Tutorial: Wie man mit dem neuen HTTP-Client Daten lädt und speichert

Angular Pro-Tipps: #2 – HTTP-Client


Eine der neuen Funktionen in Angular 2 ist der verbesserte und neue HTTP-Client. Damit lassen sich Anfragen an Webressourcen wie zum Beispiel eine Backend-Schnittstelle einfach programmieren. Mit dem neuen HTTP-Client von Angular kann man nun außerdem kinderleicht Daten laden und wieder speichern.

Bisher gelernt

Angular Pro-Tipps von Aaron Czichon

Bisher haben Sie gelernt, wie Sie mit den in Angular 2 eingeführten Pipes umgehen. Diese können genutzt werden, um Daten und Objekte vor der Anzeige in der View und/oder vor dem Rendering zu transformieren und entsprechend zu formatieren. Wenn Sie etwa ein Datum in einem bestimmten Format anzeigen wollen, können Sie hierfür eine Pipe verwenden und müssen nicht das eigentliche Datenobjekt bearbeiten. Im zweiten Teil geht es nun um den HTTP-Client in Angular.

Der HTTP-Client in Angular

Der HTTP-Client von Angular ist kein Core-Modul. Das heißt, es ist nicht in der Standard-Library von Angular 2 enthalten. Das bietet unter anderem zwei Vorteile:

  • Applikationen, die nicht als HTTP-Client fungieren müssen, müssen nicht das entsprechende Modul laden und sparen sich somit einige KB an Bundle-Größe.
  • Applikationen, die den HTTP-Client verwenden, können dessen Version auch unabhängig von der Core-Framework-Version verwenden. Sollte beispielsweise eine neue Angular-2-Version erscheinen und das HTTP-Client-Modul einen größeren Bug beinhalten, ist es möglich, die neue Core-Framework-Version in Verbindung mit der alten, stabilen Version des HTTP-Client-Moduls zu verwenden.

Um das HTTP-Client-Modul nutzen zu können, müssen Sie dieses erst Ihrer Applikation bekannt machen und entsprechend in den app.modules.ts importieren. Wird ein neues Projekt über die Angular CLI (ng new weather-sample) angelegt, wird das HTTP-Modul per Default gleich mit importiert:


import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Wenn Sie nun den HTTP-Client verwenden wollen, müssen Sie den HTTP-Service in Ihrem entsprechenden Modul und/oder Ihrer Komponente per Dependency-Injection laden. In diesem Weather-Beispiel sollten Sie folgende Dateistruktur haben, wenn Sie das Weather Sample über die Angular CLI angelegt haben:


-e2e
--...
-node_modules
--...
-src
--app
---app.component.css
---app.component.html
---app.component.spec.ts
---app.component.ts
---app.module.ts
---index.ts
--assets
---...
--environments
---...
--...
-angular-cli.json
-karma.config.js
-package.json
-protractor.conf.js
-README.md
-tslint.json

In diesem Beispiel wollen wir nun von der OpenWeatherMap.org-API die aktuellen Wetterdaten laden und in unserer Applikation anzeigen. Um nun den HTTP-Client verwenden zu können, wechseln Sie in app.component.ts und laden dort den HTTP-Service per Dependency Injection:


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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app works!';

  constructor(private http: Http) { }
}

Durch Erweiterung der app.component.html um ein Input-Feld, können die aktuellen Wetterdaten einer Stadt geladen werden. Dort soll der Benutzer die gewünschte Stadt eingeben können.


<h1>
  {{title}}
</h1>
<div>
  <input type="text" [(ngModel)]="city" placeholder="Enter City Here" />
</div>

Die app.component.ts muss entsprechend noch um das Feld city erweitert werden:

city = '';

Nun geht es dazu über, die app.component.ts mit dem HTTP-Client vertraut zu machen und die Wetterdaten zu laden. Dazu legen Sie eine neue Funktion an, welche den HTTP-Call ausführt.


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

import 'rxjs/rx';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app works!';
  city = '';
  weatherData: any;
  apiKey: string = 'YOUR-OPEN-WEATHER-API-KEY';

  constructor(private http: Http) { }

  private loadWeatherData(city: string) {
    return this.http.get(`http://api.openweathermap.org/data/2.5/weather?q=${this.city}&units=metric&APPID=${this.apiKey}`)
    .map(response => {
      return response.json();
    });
  }
}

Jetzt müssen Sie lediglich noch die app.component.ts um eine Funktion erweitern, die dann ausgeführt wird, sobald der Benutzer das Input-Feld wieder verlässt. Die app.component.html muss entsprechend um das Blur-Event erweitert werden.

Im letzten Schritt müssen Sie nun die Applikation dahingehend erweitern, dass die geladenen Wetterdaten angezeigt werden. app.component.html:


<h1>
  {{title}}
</h1>
<div>
  <input type="text" [(ngModel)]="city" (blur)="onBlur()" placeholder="Enter City Here" />
</div>
<div>
  <div>
    <h4>Location</h4>
    <p>{{weatherData?.name}}</p>
  </div>
  <div>
    <h4>Current Weather</h4>
    <p>{{weatherData?.weather[0].main}}</p>
  </div>
  <div>
    <h4>Temperature</h4>
    <p>Temperature: {{weatherData?.main.temp}}° <br />
    Temperature Max: {{weatherData?.main.temp_max}}° <br />
    Temperature Min: {{weatherData?.main.temp_min}}°</p>
  </div>
  <div>
    <h4>Humidity</h4>
    <p>{{weatherData?.main.humidity}}%</p>
  </div>
</div>

app.component.ts:


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

import 'rxjs/rx';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'app works!';
  city = '';
  weatherData: any;
  apiKey: string = 'ff7e80308c9a9afdd6dbcf582fa2fd98';

  constructor(private http: Http) { }

  onBlur() {
    this.loadWeatherData(this.city).subscribe(result => {
      this.weatherData = result;
    });
  }

  private loadWeatherData(city: string) {
    return this.http.get(`http://api.openweathermap.org/data/2.5/weather?q=${this.city}&units=metric&APPID=${this.apiKey}`)
    .map(response => {
      return response.json();
    });
  }
}

Unterschiede zum HTTP-Client in Angular

Angular 1 hat im HTTP-Client die sogenannten Promises genutzt, um Daten über AJAX nachzuladen oder zu speichern. Angular 2 hingegen kommt standardmäßig mit der RxJS Library. Diese bringt das Observable-Pattern in den Datenfluss der Angular-2-Applikation, wodurch jede Datenquelle prinzipiell zu einem „Daten-Stream“ wird.

Hinweis: Sollten Sie sich noch nicht mit RxJS befasst haben, aber dennoch schon Angular 2 verwenden wollen, können Sie ein Observable auch in einen Promise konvertieren. Die onBlur Funktion würde dann so aussehen:


onBlur() {
    this.loadWeatherData(this.city).toPromise().then(result => {
      this.weatherData = result;
    });
  }

Die Empfehlung ist jedoch, sich mit den Programmierparadigmen von RxJS auseinander zu setzen.

Angular 2 nutzt, wie auch schon Angular 1, ein paar Default-Header, um mit der Ressource zu kommunizieren. Auch hier können Sie, wie aus Angular 1 bekannt, eigene Header definieren.
Sollten Sie also eine API haben, welche beispielsweise einen Authorization-Token im Header mitschicken soll, können Sie dies mit einem eigenen Header tun. Ein Beispiel wäre dies:


private loadWeatherData(city: string) {
    let headers = new Headers({
      'Content-Type': 'application/json',
      'Authorization': 'Bearer YOUR-AUTHORIZATION-CODE'
    });
    return this.http.get(`http://api.openweathermap.org/data/2.5/weather?q=${this.city}&units=metric&APPID=${this.apiKey}`, headers)
    .map(response => {
      return response.json();
    });
  }

Der Typ Headers kann über das @angular/http-Modul importiert werden.

Fazit

Der in Angular 1 schon sehr gute HTTP-Client wurde in Angular 2 komplett neu erdacht und das alte Konzept in das neue, einfachere Konzept von Angular 2 überführt. Hierbei haben sich die Entwickler nichts grundlegend Neues ausgedacht, sondern bestehende Paradigmen wie RxJS verwendet, um so das Leben der Entwickler leichter zu machen. Durch die Verwendung von Observables als Rückgabe-Objekte ist es nun auch sehr einfach, HTTP-Streams entgegen zu nehmen und in der Applikation weiter zu verwenden.

Hierzu noch ein paar nützliche Links, falls Sie tiefer in das Thema einsteigen wollen:

Ressouren und Github

Es gibt zur Artikel-Serie auch das dazugehörige Github-Repository mit den jeweiligen Projekten:
Angular 2 Pro-Tipps

Lesen Sie auch: Angular 2 Pro-Tipps: #1 – Angular Pipes

Aaron Czichon

Aaron Czichon hat mit 14 Jahren mit Softwareentwicklung angefangen und sich PHP und HTML beigebracht. Ausbildung zum Fachinformatiker Anwendungsentwicklung, seitdem bei der cellent AG in Stuttgart als Softwareentwickler im Projektumfeld mit JavaScript und .NET tätig.\rNebenberuflich freier Entwickler mit seiner WebAtlas GbR. 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 und referiert überwiegend über das Ionic Framework.