Consuming a REST API With Angular Http-Service in Typescript

Feb 01, 2016 reading time 7 minutes

Consuming a REST API With Angular Http-Service in Typescript

Updates

  • 19.09.2018 – Updated Angular Syntax
  • 19.08.2017 – Updated to ASP.NET Core 2.0 & new HttpClientModule

 

Hey,

with this blog post I want to show you how to create a data service to consume (not only) an ASP.NET REST API with the angular http module.

In my recent blog post Getting started with Visual Studio Code, AngularJS and Typescript I have already mentioned how to start and to install the complete angular environment with corresponding tools.

Now I want to show you an example dataservice to call your favourite API.

Configuration

It’s always a good thing if you have your configuration separated stored anywhere in your application. I always go for the environment file where I store all my values. If anything changes there, like a version of the api which is stored in the url or the endpoint/server whatever, I can do those changes immediately at one point.

export const environment = {
    server: 'http://localhost:5000/',
    apiUrl: 'api/';
};

Notice the injectable attribute to generate the metadata to make the service available through DI in other modules.

You can read more about DI in Angular in this blog post Dependency Injection in Angular

Now we have this going we can generate our service:

The Service

First of all you have to create a module which only contains a service which is only responsible for calling an API with a specific endpoint.

import { HttpClient, HttpEvent, HttpHandler, HttpInterceptor, HttpRequest } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
import { environment } from '../../environments/environment';

@Injectable()
export class DataService {

    private actionUrl: string;

    constructor(private http: HttpClient, private configuration: Configuration) {
        this.actionUrl = `${environment.server}${environment.apiUrl}values/`;
    }

    getAll<T>(): Observable<T> {
        return this.http.get<T>(this.actionUrl);
    }

    getSingle<T>(id: number): Observable<T> {
        return this.http.get<T>(this.actionUrl + id);
    }

    add<T>(itemName: string): Observable<T> {
        const toAdd = { itemName };

        return this.http.post<T>(this.actionUrl, toAdd);
    }

    update<T>(id: number, itemToUpdate: any): Observable<T> {
        return this.http
            .put<T>(this.actionUrl + id, itemToUpdate);
    }

    delete<T>(id: number): Observable<T> {
        return this.http.delete<T>(this.actionUrl + id);
    }
}


@Injectable()
export class CustomInterceptor implements HttpInterceptor {

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        if (!req.headers.has('Content-Type')) {
            req = req.clone({ headers: req.headers.set('Content-Type', 'application/json') });
        }

        req = req.clone({ headers: req.headers.set('Accept', 'application/json') });
        return next.handle(req);
    }
}

Do not forget to add your interceptor like

{ provide: HTTP_INTERCEPTORS, useClass: CustomInterceptor, multi: true },

This data service gets the configuration we did and the HTTP-Service via DI. We included it over the new module-loading-syntax.

It is also important to tell the http-calls which header to use. “Application/Json” in this case. We are doing this via an interceptor and the new HttpClientModule.

Now you can include, inject and use this service to make http-calls to your API like this:

import { Component, OnInit } from '@angular/core';
import { ToasterService } from 'angular2-toaster/angular2-toaster';
import { SlimLoadingBarService } from 'ng2-slim-loading-bar';

import { DataService } from '../../shared/services/dataService';

@Component({
    selector: 'app-home-component',
    templateUrl: './home.component.html'
})

export class HomeComponent implements OnInit {

    message: string;
    values: any[];

    constructor(
        private dataService: DataService,
        private toasterService: ToasterService,
        private slimLoadingBarService: SlimLoadingBarService) {
        this.message = 'Hello from HomeComponent constructor';
    }

    ngOnInit() {
        this.slimLoadingBarService.start();

        this.dataService
            .getAll<any[]>()
            .subscribe((data: any[]) => this.values = data,
            error => () => {
                this.toasterService.pop('error', 'Damn', 'Something went wrong...');
            },
            () => {
                this.toasterService.pop('success', 'Complete', 'Getting all values complete');
                this.slimLoadingBarService.complete();
            });
    }
}

I think this should be basically it. Pay attention to the (normally) typed answer you get from the service

(data: any[]) =>

should be in your application

 this.dataService
            .getAll<MyTypedItem[]>()
            .subscribe((data: MyTypedItem[]) => this.values = data,

and to the subscribe after calling the “GetAll”-Method from the service.

Hope you enjoyed it and a lot more: I hope this helps.

Bye

Fabian

GitHub:

Angular // Webpack // ASP.NET CORE WebAPI Starter Template

or

https://github.com/FabianGosebrink/ASPNET-ASPNETCore-Angular-Webpack/tree/master/AngularCLI

https://auth0.com/blog/2015/05/14/creating-your-first-real-world-angular-2-app-from-authentication-to-calling-an-api-and-everything-in-between/

https://auth0.com/blog/2015/10/15/angular-2-series-part-3-using-http/

https://auth0.com/blog/2015/09/17/angular-2-series-part-2-domain-models-and-dependency-injection/

https://auth0.com/blog/2015/09/03/angular2-series-working-with-pipes/

https://angular.io/docs/ts/latest/guide/architecture.html