An Angular application running in a browser uses remote services to retrieve and update data. The communication occurs over HTTP. Browsers widely support XMLHttpRequest (XHR) over HTTP. Out of the box, Angular provides services that ease making XHR calls in an Angular application. JSON (JavaScript Object Notation) is a good format for exchanging data between the server and a browser application. It is lightweight and efficient, considering JSON objects are simple text. Also, browsers readily interpret JSON data without needing additional libraries.
This chapter goes over getting started with an HttpClient service. We enhance the sample application to import the module and the service. Building remote services is beyond the scope of this book. To demonstrate interfacing with a typical RESTful remote service, we mock a sample service that provides and updates superhero data.
The GET, POST, PUT, and DELETE HTTP methods are largely used. The chapter explains implementing these methods for retrieve, create, update, and delete actions.
Getting Started
This chapter covers using the HttpClient Angular service that helps make XHR calls (XML HTTP Request) from an Angular application. It is part of the Angular module, HttpClientModule. We import it to make use of the HttpClient Angular service.
superheroes-material-design, which contains all the Material Design components and functionality
app-routing, which contains the routing logic for the single-page application
app, the main module for the application
Generate a Module for Remote HTTP Calls
Generate a Service for Service Calls
Note
Chapter 7 discusses building, injecting, and using Angular services. The service is a reusable TypeScript class in Angular, which can be instantiated and injected into components and other services. Unlike components and directives, services are without a user interface.
Import HTTP Client Module
The Primary App Module Imports the New AppHttpCallsModule
We imported HttpClientModule to be able to make API calls. We created a new module, AppHttpCallsModule, and added a new service to it. This service is expected to contain the code to make HTTP calls.
AppHttpCallsModule is imported in the primary app module along with SuperheroMaterialDesignModule. The new service, Hero Data Service, can be used in all modules referenced by the app module. The service is for making HTTP calls for hero data.
GET: Retrieves data about one or more entities in the system. The entity could be an order, student, customer, or so forth. In the sample application, superheroes are the entities.
POST: Creates an entity.
PUT: Updates the complete entity.
PATCH: Updates partial data in an entity.
DELETE: Removes an entity from the system.
Mock Data
For the purpose of the sample application, let’s run a Node.js-based service that returns data from a mock JSON file. Consider creating a JSON file with superhero data.
JSON Server is an npm package that creates an ExpressJS-based web server from a mock JSON file. A typical service may have business logic and data access logic for saving and retrieving data from a database or a data source.
To set up JSON Server, install it using Yarn or npm. Consider the command in Listing 16-5. It is installed globally on the machine. Most dependencies install at the project level. Considering JSON Server is a developer tool used across projects, we install it at globally at the machine level.
Install JSON Server for Mock Data
Run JSON Server
Now, access the mock response by attempting the following URL in a browser: http://localhost:3000/. In Figure 16-1, /heroes is an array object based on the structure defined in the mock JSON file.
Note
To access a mock JSON response mimicking a real server-side API, we chose JSON Server. You may use any tool for this purpose, as long as it supports RESTful services.
Use HttpClient to Make HTTP Calls
The superhero data service imports HttpClient from @angular/common/http. The Angular module was imported in the preceding section.
HTTP Call Using HttpClient
getHeroes uses the httpClient instance and makes a GET call, which makes a remote HTTP call. It returns an observable, which is assigned to a variable named heroes (see line 11).
Iterate to Create Hero Objects from Service Response
The subscribe function is invoked as the get function call succeeds or fails. If the GET call succeeds, the result is a list of superheroes. The success callback function parameter data is in line 4 of Listing 16-8. It is the result from the HTTP call.
We perform a null check and iterate through the list of heroes. Note lines 5 to 13. Fields from the response are assigned to a new JSON object and logged to the console. For simplicity, we are logging the data to the console. We may create a promise or an observable to provide the data to the calling function. Typically, a calling function is part of a component or another service.
Note
We cannot return the superhero object from the service function. The success callback on subscribe is invoked asynchronously. The function control returns the component class (or any other calling function) after invoking the get function on line 2. The function was already returned before executing lines 4 to 13. We create a promise or an observable to return data from this function.
Explicitly Type Response Object
An advantage of using TypeScript is that we can define a class or a type for the response structure. It helps simplify the code, and it is a good practice.
In Listing 16-9, the httpClient get function is in line 2. It uses a template of type Array of the Superhero object. The Superhero class is structured to match the API response.
Remote Service Response Typed to a Class in Angular
Note
Unlike the prior sample, we have not created a separate object for a returned value from the get function. It returns an observable. We chained the function call with a subscribe(). It is useful, considering the heroes observable is not used in other places in the function. Creating a separate variable is redundant.
Return Data to the Calling Function
Return Observable from HTTP Client to the Calling Function
Results from the Angular Service Assigned to a Class Variable
Results from the Angular Service Assigned to a Class Variable
Assign Hero Service Result to An Observable
Async Pipe on Observable
In some cases, we need to change the object structure, and process the response data with additional logic. In this scenario, the Angular service subscribes to the observable returned by the HttpClient get() function. It processes the data and returns the results to the calling function.
The function cannot directly return the results. Considering the subscribe callback function is invoked asynchronously, control from the Angular service getHeroes() function already returns to the calling function. In this scenario, we can create and return another observable or promise from the Angular service getHeroes() function.
Angular Service getHeroes() Function Returning Observable
Line 2 creates and returns an observable. The calling function has reference to the observable. In the calling function, the subscribe function is called on the new observable created by getHeroes().
The static create() function on the Observable class acts as a factory to create an observable. It expects a callback function with an input parameter for the observer. Results can be accessed by the subscriber (a calling function or the component), with the next() function call on the observer (see line 11).
The observable returned by the HttpClient get() function is subscribed in line 5. We iterate through the results from the remote service. Perform additional processing or transformation of the object structure. In line 8, a placeholder is used for this purpose. Afterward, we iterate through all the results, and use the next() function on the observer to send data to the subscriber in the calling function (see line 11).
Note
Follow the links in the references section at the end of chapter to learn more about RxJS and observables.
Angular Service getHeroes() Function Returning Promise
The getHeroes() function creates and returns a promise (see line 2). The observable returned by the HttpClient get() function is subscribed in line 5. We iterate through the results from the remote service. Perform additional processing or transformation of the object structure. In line 8, a placeholder is used for this purpose.
Angular Component Using the Promise
Angular HTML Template Component Showing the Results
Note
Most HTTP services, especially the services that adhere to REST standards, return data about a single entity with the ID specified in the URL. Consider a sample URL with JSON Server, http://localhost:3000/heroes/001. It returns hero with ID 001. We can use the HttpClient instance get() method with the relevant URL to retrieve a single entity or a subset of the list.
Handling Errors with Remote Service Calls
An Angular application needs to handle HTTP errors that occur while using the remote service. The errors need to be handled gracefully, rather than crashing the whole page.
Subscribe on an Observable
Observable Handling Errors
Remember, the error handler is on the subscribe function of the observable. Referring back to Listing 16-20, if the observable was returned directly from the Angular service, without a subscribe(), it loses the option to handle errors. If there are multiple calling functions, the code needs to be integrated in all of those places.
To address this scenario, we may pipe an error handling operator with the observable. See line 7 in Listing 16-20. The Angular service function returns the observable without a subscription. As the error occurs, the Angular service still handles the error gracefully.
Observable Pipes Error Handler
POST Calls with HttpClient
POST Method with HttpClient
Create Superhero Component
Note
The POST call is not made until the observable is subscribed. Just calling createHero on the dataService instance does not invoke the API. In the sample, we subscribe from the component in line 14.
PUT Calls with HttpClient
Update Entity with HTTP Client
Note
Similar to PUT, PATCH is an HTTP method to update an entity in the system. A RESTful API, while updating an entity, uses PATCH to update a subset of fields without overriding the whole entity, whereas PUT is used to update the entire entity. On the HttpClient instance, we can use the patch function; however, the behavior depends on remote API implementation.
DELETE Calls with HttpClient
Delete Entity with HTTP Client
Conclusion
Angular provides utilities to request XHR (XMLHttpRequests) calls out of the box with the HttpClient service. It is part of the @angular/common/http module. In this chapter, we started with instructions to include needed dependencies. It is a good practice to separate remote service integration to a new module.
The chapter described using a JSON Server npm package to mock API responses. JSON Server is one of many options to mock API responses. We may use any package or library that helps mimic remote services.
The chapter also explained using the get() method on an HttpClient instance to retrieve data. It makes the HTTP call using the GET method. Use the post() method on an HttpClient instance to create an entity. It makes the HTTP call using POST method. Use the put() or the patch() method on an HttpClient instance to update an entity. It makes the HTTP call using PUT or PATCH, respectively. Use the delete() method on HttpClient instance to delete an entity. It makes the HTTP call using the DELETE method.
Exercise
Create dinosaur data in JSON format. Save the file with a .json extension. Use JSON Server (or any other mocking tool) to serve the data as a remote service.
Integrate the dinosaur list screens using the screens created throughout the book with the remote service. Use GET calls to retrieve data.
Integrate the details screen with a GET call that retrieves data by ID. Use the dinosaur ID specified in browser URL and in the XHR call.
Integrate a reactive form for creating a dinosaur with the remote service. Use the POST call to create a dinosaur entity.
References
Angular documentation on HttpClient (https://angular.io/guide/http)
JSON Server npm package (www.npmjs.com/package/json-server)
Learn RxJS and create an observable (www.learnrxjs.io/operators/creation/create.html)