left-icon

Angular Succinctly®
by Joseph D. Booth

Previous
Chapter

of
A
A
A

CHAPTER 18

Getting Data Using HTTP

Getting Data Using HTTP


Many applications use a database to persist the information the application has collected. It could be Microsoft SQL Server, Oracle, or another database. In this chapter, we will cover how to consume a web service to collect some data and possibly write it back.

Web services

The HTTP protocol was designed to allow requests to be sent to web servers and responses to be retrieved from the servers. Browsers are designed to make requests of webpages, and typically bring back complete webpages to the browser. When you enter a URL in a browser address bar, such as www.syncfusion.com, the browser contacts the DNS server that looks up the IP address for the website and sends a request to that website, which returns with a full HTML webpage to display to the user.

A web service operates very similarly, except rather than return a full webpage, it typically returns a small amount of formatted data that an application can then use as needed. The data is generally formatted as XML documents or a JSON string. Angular works with JSON data very well, and we will look at how to communicate using JSON-oriented web services.

JSON test website

The JSON test website provides a few sample web service calls that return JSON data. For example, if you enter the URL http://ip.jsontest.com/ in your browser, you will not get a full website back, but rather a JSON string with your IP, as shown in the following code.

Code Listing 153

{"ip": "127.0.0.1"}

Angular provides the functionality to make the API request and gets the returned data into your application. There are thousands of APIs available. Many are free, but require you to get an access key to use them.

JSON format

JSON (JavaScript Object Notation) is an open-source format for transmitting data objects. It is designed to be both compact and readable by humans. Although JSON is language independent, you can see its JavaScript roots.

JSON elements consist of a property name and a value, such as the IP example in Code Listing 153. A JSON object may have multiple elements. The JSON object is delimited by { }, with the collection of elements between the braces. For example, you might represent a person with a JSON object of:

Code Listing 154

{ "name": "Jonathan" , "phone": "555-1212", "email": [email protected] }

The object is readable by both humans and computer applications. You’ve also seen some JSON files in earlier chapters as you’ve set up the Angular environments.

The property values can be numeric, string, Boolean, or date values. You can also have a collection of objects by nesting the objects with an outer set of { } characters.

You can make a collection of objects by providing an object name and the [ ] delimiters. Within the brackets could be multiple objects. For example, the JSON in the following code represents various phone numbers a person might have.

Code Listing 155

"PhoneNumbers" : [

         { "type": "home","areaCode": "215","number": "555-1212" },  

         { "type": "mobile","areaCode": "610","number": "867-5309" },

        ]

The JSON structure provides flexibility to be as simple or complex as your application needs it to be.

Web commands

Angular provides the HTTP module that allows you to perform the following basic web methods:

  • GET: Retrieve data from a URL; query parameters can be used.
  • POST: Like GET, except parameters are passed in the request body.
  • HEAD: Like GET, but the server only returns the HTTP headers.
  • PUT: Upload a file directly to the web server.
  • DELETE: Delete a resource from the web server.

We are only going to focus on GET and POST, which are the most commonly used HTTP web requests. If you’ve designed your web service, you can support the PUT and DELETE verbs, but by their nature, they pose security risks.

Angular HTTP

Angular includes a base library called @angular/common/http, which contains the methods needed to make web calls. You will need to import the HttpClientModule from this library, as shown in the following code. This would typically be done in the app.module code.

Code Listing 156

import {HttpClientModule} from '@angular/common/http';

Next, modify your component’s constructor to save the Http module, such as:

Code Listing 157

    constructor(private _http: HttpClient) {

    }

This is the basic setup you will need for components that will make HTTP requests.

Root module

Since we want the HTTP services to be available throughout the application, we can add the Http module to our app.module.ts file, as shown in the following listing.

Code Listing 158

import { HttpClientModule }    from '@angular/common/http';

@NgModule({

  imports: [ BrowserModule, HttpClientModule],

Be sure to update your root module with these additions if they are not already there.

Web service

You should generally wrap the web calls in a service so they can be used by different components as needed. For example, we are going to create a WebService class to handle all the HTTP calls. You could import the WebService as a provider and save it to a private variable during the constructor code.

Code Listing 159

import { WebService } from '../services/WebService';

  @Component({

    providers: [SoccerService,WebService]           

   })

export class AppScoring {

     public constructor( private _web: WebService ) { }

At this point, the component has access to the service and will be able to use any of the methods the web service chooses to provide. For our example, we are simply going to call the IP method from the JSON test website and display the IP address in our template. With a few tweaks, you could easily use this service to restrict access to certain sections of the template to a whitelist of acceptable IP addresses.

Creating the web service

The web service will handle the actual interaction with the sites or API you wish to use. You should start with the appropriate imports from the Angular libraries and from the Reactive Extensions (RxJS) library.

Note: The Angular HTTP services rely on JavaScript observables, which is what the RxJS libraries are designed to handle. In general, an observable is a way to allow JavaScript to run asynchronously.

Web service imports

The WebService class will need the following imports to set up HTTP and the observables.

Code Listing 160

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

import { HttpClient }  from '@angular/common/http';

Since it is a service, we will need to make it injectable and save the Http module during the constructor.

Code Listing 161

@Injectable()

export class WebService {

    constructor(private _http: HttpClient) {

    }

With this basic setup, we can start adding the various methods to make HTTP calls. Our first method will call the ip.jsontest web service to get the IP address of the site visitor. This could be useful for logging purposes or to whitelist access to certain areas of the website.

Code Listing 162

    private _IPURL: string = "http://ip.jsontest.com";

    public getIP (): {

        return  this._http.get(this._IPURL);

   }

You could also create other public methods to pass a URL to call and return the results.

Code Listing 163

    public CallURL(_URL: string)  {

        return  this._http.get(_URL);

    }

You could also add different methods to extract object properties, depending on the structure of the JSON data that is being returned.

Using the service

Assuming your component refers to the service as _web, we need to perform two steps. First is to declare a component property to hold the results from the service.

Code Listing 164

  public IPAddr: string;

The second step is to subscribe to the service method. Keep in mind that the web service is called asynchronously, so your TypeScript code will keep going after the call to the getIP() method. The subscribe() method is basically telling the method: go off and do your thing, but I want you to do something as soon as you are done—in this case, simply put the results into my variable.

Code Listing 165

_web.getIP().subscribe( (data:string) => this.IPAddr = data["ip"] );

Once the getIP() method completes (and returns the IP address), we tell the method to take the results and put it into our IPAddr variable. In this, we are getting a simple string. We could also define a class that matches the web service JSON structure and have the service copy the entire JSON structure into an object created from our class.

Passing parameters

There are two ways to pass parameters to a web service. You can pass them on the GET query string if the parameters are part of the URL. For example, the jsontest site has a service that will compute an MD5 from a given text string. If we pass the following URL:

Code Listing 166

http://md5.jsontest.com?text=AngularRocks

The site will return a JSON string, as shown in the following code.

Code Listing 167

{

   "md5": "c2690756861ba21dc367ab72b0621906",

   "original": "AngularRocks"

}

The only caveat to keep in mind is that the parameters passed on the query string must be URL-encoded, and most browsers limit the URL length to 2,048 characters. Fortunately, TypeScript includes a function that allows us to easily do URL encoding.

Code Listing 168

    public getMD5( str: string) {

        let finalUrl = this._MD5URL + encodeURI(str);   

        this._web.CallURL(finalUrl).

           subscribe( (data:string[]) => this.md5= data["md5"]);              }

The rest of the code to use the GET method and a query string parameter is the same. Don’t forget to use the custom extraction method to get the proper JSON parameter.

Getting a collection

There may be times that you need to get a collection of objects, rather than just a single string from the HTTP call. For example, we could create a file called teams.json and place it in our assets folder.

Code Listing 169

[

    { "id":1,"name":"Old Menu United","type":"Over 30"},

    { "id":2,"name":"422 Nomads","type":"Over 30"},

    { "id":3,"name":"FC Dauntless","type":"Over 30"},

    { "id":4,"name":"Kellie's Kickers","type":"Over 30"},

    { "id":5,"name":"Blue Devils","type":"Over 30"},

    { "id":6,"name":"Torn Achilles","type":"Over 30"}      

]

We would now adapt our HTTP call in the web services module to return a collection, rather than a general object. You can also return a single object, simply by specifying the interface name rather than the collection syntax (shown in Code Listing 170).

Code Listing 170

    public getTeams()

    {

      let _TeamURL: string = "assets/teams.json";

      return this._http.get<iTeam[]>(_TeamURL);

    }

Now, when the getTeams() method is called, it will attempt to shape the data into a collection of team objects. You can create a Teams collection in the component, and pass the results of the getTeams() call to a function. This function can assign the result to the Teams collection variable. By going through a function, you can provide other code that might need to be done once the web service call is completed.

Code Listing 171

{

 …

  _web.getTeams().subscribe( (data) => this.LoadTeamList(data))

}

private LoadTeamList(data) {

    this.Teams = data;

    // Other tasks to do

  }

Tip: Writing a method to gather the data gives you more flexibility than simply assigning the data with the subscribe call.

Error handling

The second parameter to the subscribe() is the function to call if an error occurs.

Your component code can access the error by checking for it during the subscribe call, as shown in the following code example.

Code Listing 172

_web.getIP().subscribe( (data:string) => this.IPAddr = data["ip"],

Error => this.ErrMsg = Error.message);

This will copy the error message to the component string property called ErrMsg. You could optionally display it in your template using the *ngIf directive, but the error message might not be meaningful to the end user.

The Error object has several additional properties (as shown in Code Listing 173), such as the HTTP status code and text, the original URL requested, and more.  You can capture these properties by saving the full error object, rather than just the text message, to a component property.

Code Listing 173

 "status":404,

"statusText":"Not Found",

"url":"http://localhost:4200/assets/teams.json",

"ok":false,

"name":"HttpErrorResponse"

Summary

The HTTP module makes web service and API calls simple— just remember that the calls are asynchronous, so you need to subscribe to get the results. This will allow your application to run quickly, even as it reaches out to other sites for JSON information.

Scroll To Top
Disclaimer
DISCLAIMER: Web reader is currently in beta. Please report any issues through our support system. PDF and Kindle format files are also available for download.

Previous

Next



You are one step away from downloading ebooks from the Succinctly® series premier collection!
A confirmation has been sent to your email address. Please check and confirm your email subscription to complete the download.