While sending HTTP requests to our server, we need to use the Angular HttpClient. Of course, we may handle all the HTTP requests from every component and process the response as well, but it is not a good practice. It is much better to make the repository for your requests and then send the request URI to that repository. The repository should take care of the rest.

For the complete navigation and all the basic instructions of the Angular series, check out: Introduction of the Angular series.

To download the source code for this article, you can visit our GitHub repo.

So, let’s start with the environment files first.

Support Code Maze on Patreon to get rid of ads and get the best discounts on our products!
Become a patron at Patreon!

Working With Environment Files

While this project is in development mode the server’s endpoint address is the http://localhost:[Port Number]. With the application in the production environment, the endpoint is different, something like www.accountowner.com. So, we want Angular to take care of that. That said, in the development mode, it should send requests towards the development URI, and in the production environment to a different address.

Let’s implement that.

In Visual Studio Code’s explorer window, we are going to search for the environments folder: src/environments. Inside that folder, we are going to find two files, the environment.prod.ts, and the environment.ts. We are going to use the first one for the production configuration and the second one for the development configuration.

So, let’s start with the environment.prod.ts modification:

export const environment = {
  production: true,
  urlAddress: 'http://www.accountowner.com'
};

Next, let’s modify the environment.ts file:

export const environment = {
  production: false,
  urlAddress: 'http://localhost:5000'
};

Now we are going to create a service, which we can use to get the valid environment urlAddress.

Let’s create a new environment-url.service.ts file:

ng g service shared/services/environment-url --skip-tests

This command will create a new shared/services folders, and inside the service file:

CREATE src/app/shared/services/environment-url.service.ts (143 bytes)

About the Angular Services

Services are just classes, which provide us with some business logic relevant to our components. These services must be injected into a component using constructor injection. Furthermore, our code becomes more maintainable and readable once we extract the logic from a component to service.

When we want to use a service, we need to inject it into a component’s constructor. Therefore, it is always decorated with the @Injectable decorator.

We should use services whenever we have code that we can reuse in other components, or extract part of the code from our components.

That said, let’s continue our work with the environment files by modifying the environment-url.service.ts file:

import { environment } from './../../../environments/environment';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class EnvironmentUrlService {
  urlAddress: string = environment.urlAddress;

  constructor() { }
}

The urlAddress property accepts the value of the urlAddress defined in the environment file. Angular knows if it is a production or development environment and is going to supply us with a valid value of that urlAddress. We can check that in the angular.json file:

"configurations": {
  "production": {
    ...
    "fileReplacements": [
      {
        "replace": "src/environments/environment.ts",
        "with": "src/environments/environment.prod.ts"
      }
    ],

We can see that Angular will replace files in production mode.

Creating Angular Repository File

Now we can configure the HttpClientModule and create the repository service.

First, we need to import the HttpClientModule inside the app.module.ts file:

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

Then let’s place it inside the imports array:

imports: [
    BrowserModule,
    AppRoutingModule,
    BrowserAnimationsModule,
    HttpClientModule,
    CollapseModule.forRoot()
  ]

After that, let’s create a service file and name it owner-repository.service.ts. We are going to place it in the same folder in which the environment service resides. In this service, we are going to create GET, POST, PUT, and DELETE requests for the owner entity from our server API:

ng g service shared/services/owner-repository --skip-tests

After the file creation, we are going to create a new _interfaces folder under the app folder, and add a new owner.model.ts file:

export interface Owner{
  id: string;
  name: string;
  dateOfBirth: Date;
  address: string;
}

Once we have our interface in place, we can modify the repository file:

import { Owner } from './../../_interfaces/owner.model';
import { EnvironmentUrlService } from './environment-url.service';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class OwnerRepositoryService {

  constructor(private http: HttpClient, private envUrl: EnvironmentUrlService) { }

  public getOwners = (route: string) => {
    return this.http.get<Owner[]>(this.createCompleteRoute(route, this.envUrl.urlAddress));
  }

  public createOwner = (route: string, owner: Owner) => {
    return this.http.post<Owner>(this.createCompleteRoute(route, this.envUrl.urlAddress), owner, this.generateHeaders());
  }

  public updateOwner = (route: string, owner: Owner) => {
    return this.http.put(this.createCompleteRoute(route, this.envUrl.urlAddress), owner, this.generateHeaders());
  }

  public deleteOwner = (route: string) => {
    return this.http.delete(this.createCompleteRoute(route, this.envUrl.urlAddress));
  }

  private createCompleteRoute = (route: string, envAddress: string) => {
    return `${envAddress}/${route}`;
  }

  private generateHeaders = () => {
    return {
      headers: new HttpHeaders({ 'Content-Type': 'application/json' })
    }
  }
}

Repository Code Explanation

Let’s explain this code.

First, we inject the Angular HttpClient and the environment variable into the constructor. Then we create functions that are going to wrap up our requests. The getOwners function is a wrapper for the GET request. It accepts the route parameter of the string type (api/owner) and then combines it with the environment variable (localhost or www…). After all of that, we are going to have the route like http://localhost:5000/api/owner if it is a development environment, which perfectly fits our requirements on the server-side.

The second function, createOwner, is a wrapper for a POST request. It also generates a route, but additionally receives a body (an entity which we are creating) and generates headers. For this example, we are just creating the Content-Type inside header. But if we need additional values inside the header, we could just add another key-value pair inside the HttpHeaders object.

The updateOwner function is pretty much the same as the createfunction, except, it sends the PUT request. Lastly, the deleteOwner function is a wrapper for the DELETE request which accepts the route like (api/owner/id). Both of these functions are missing a strongly typed HTTP method (put and delete) because we don’t expect any object as a response from the server. If everything goes well, we are going to get a 204 as a response without a response body.

The Subscription on the HTTP Calls

These wrapper functions need a subscription in order to work. In this post, we are only creating a repository with the HTTP calls. But as soon as we start creating our pages, we are going to use the subscription.

For now, we are just going to show you one example of a subscription:

owners: Owner[];

constructor(private repo: OwnerRepositoryService) { }

private consumeGetFromRepository = () => {
  this.repo.getOwners('api/owner')
  .subscribe(own => {
    this.owners = own;
  })
}

As you may notice, we are calling the getOwners function from the repository, but that function won’t be executed until we call the subscribe function. The result from the response is going to be stored in the own parameter.

Conclusion

Excellent, now we have our repository prepared and we are ready to create components, which are going to use this repository functions to show results in a browser.

In the next part of the series, we are going to show you how to use lazy content loading in Angular. Additionally, we will show the result data on the page.

Liked it? Take a second to support Code Maze on Patreon and get the ad free reading experience!
Become a patron at Patreon!