Tutorial: Wie man mit dem neuen HTTP-Client Daten lädt und speichert
Tutorial: Wie man mit dem neuen HTTP-Client Daten lädt und speichert
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.
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 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:
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();
});
}
}
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.
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:
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