Angular 18 In-memory Web API tutorial: Mocking CRUD APIs in Angular

Angular 18 In-memory Web API tutorial: Mocking CRUD APIs in Angular

The tutorial will showcase the utilization of the Angular 18 framework in conjunction with the in-memory web API module. This demonstration will illustrate the development of a backend-less application, simulating a REST API backend with standard CRUD operations. Such an approach proves invaluable for Angular developers engaged in front-end application development without an available backend infrastructure.

In this tutorial, we will leverage Angular's angular-in-memory-web-api module to fabricate a pseudo REST API using an in-memory database, thereby circumventing the need for a live backend server. This proves especially beneficial when backend services are not yet accessible during the initial stages of front-end development.

Consider the common scenario wherein developers are tasked with implementing new features for a front-end application, yet the requisite HTTP endpoints are not yet operational or accessible to the front-end development team. This predicament is commonplace in large teams comprising both front-end and back-end developers.

As a temporary solution during such development phases, developers often resort to creating a mock server that emulates the behavior of a fully functional HTTP REST API. This mock server performs all CRUD operations expected from a typical backend, while the data is stored locally within the front-end application.

To commence, we will delve into Angular's In-Memory Web API, followed by the creation of a sample mock API capable of emulating basic CRUD operations. This mock API can then be seamlessly integrated into Angular 18, facilitating the development of fully functional front-end applications independent of backend dependencies.

Introducing the in memory web api for angular

The angular-in-memory-web-api module provides an in memory data store where you can create and fetch data and simulates a real REST API back-end. It intercepts Angular 18 HttpClient requests that would otherwise go to the remote server and redirects them to an in-memory data store that you control.

It serves as a stand-in/proxy for your actual back-end system. Once an HTTP request is sent to the module, it intercepts it, processes it, and provides the results from memory. As a result, when you are ready to utilize a real API back-end, you will not be required to make any changes to the API endpoints that you previously provided to your Angular code.

Create, read, update, and delete items from an in-memory database using the in memory web api module instead of going through the hassle of setting up a real database and creating and exposing a real REST API server just for the sake of testing your Angular 18 application using the in memory web API module. However, this is just a temporary solution until the back-end team (or you, if you are a full-stack developer) is able to complete the back-end design and development.

This module intercepts the HttpClient (the Angular 18 HTTP client) requests that get sent to an address of an API server then simply proxy the requests to an in-memory database that you'll have to setup in your project.

Benefits of Using In-Memory Web API

  • Simulates Real API Behavior: Intercepts HTTP requests and provides responses from an in-memory database.
  • No Backend Dependency: Allows front-end development to proceed without waiting for the backend.
  • Easy Transition to Real Backend: Once the real API is ready, no changes are needed to the frontend API endpoints.

Prerequisites

To complete this tutorial, you will need to have a few prerequisites, such as:

  • Node.js and npm installed on your system. Both are required to install and run Angular CLI 18,
  • Familiarity with JavaScript and TypeScript.

That's all what you need, you can use Windows, macOS or any Linux distribution provided that you have the right Node.js version installed on your system.

This angular tutorial will take you step by step from installing Angular 18 CLI, to generating a project and creating services and components and finally setting up the in-memory web API.

Now you are ready to install Angular CLI 18 and use to create a project.

Install Angular CLI 18

You'll use Angular CLI 18 to create an Angular project. If it's not installed on your system you should run this command to install it globally:

$ npm install -g @angular/cli

If you get any permission errors, you can simply add sudo before your command in macOS and debian systems (e.g. Ubuntu) or use a command prompt with administrator privileges in Windows.

That's it! You now have a complete environment for Angular 18 development. But since Angular is for building front-ends and client side apps, and more often that not, a back-end is required, you will either need to have the back-end built for you or simulate the REST API that would be normally exported by your back-end server. In this tutorial, you'll learn to implement this latter approach.

Creating an Angular 18 Project

You can now create a project using the Angular CLI v18 as follows:

$ ng new angular-inmemory-api

You'll have to wait a little bit of time until your project is read then navigate inside the root folder and serve your project using the following command:

$ cd angular-inmemory-api
$ ng serve

You can access your project from the localhost:4200 address. Angular CLI v18 uses a live-reload server so any changes you make to your project's code will be live-reloaded in your browser.

So just leave the development server running and open your Angular 18 project in your preferred IDE or code editor (VSCode is a nice choice!)

Setting up the angular-in-memory-web-api module

Now that you've created your project, you need to set up the angular-in-memory-web-api module.

You can do that following these easy steps:

  • First, you need to install the angular-in-memory-web-api module from npm in your Angular project,
  • Next, you need to proceed by creating an Angular service that encapsulates working with the in-memory database,
  • Finally, you'll be able to use the in-memory database service in your Angular component(s).

Go back to your terminal and run the following command to install the angular-in-memory-web-api module:

$ npm install --save angular-in-memory-web-api

Next, you can create an Angular service using:

$ ng generate service data

You can also use the ng g s data instead to create the data service.

The previous command will generate two files:

  • The src/app/data.service.ts file which encapsulates the actual code of the service you just created.
  • The src/app/data.service.spec.ts file which contains unit tests for the service.

Our work will be done inside the src/app/data.service.ts file so open the file and import InMemoryDbService from the angular-in-memory-web-api module:

import {InMemoryDbService} from 'angular-in-memory-web-api'

Next, your data service has to implement InMemoryDbService and override the createDb() method:

@Injectable({
  providedIn: 'root'
})
export class DataService implements InMemoryDbService{

  constructor() { }
  createDb(){

   let  policies =  [
    {  id:  1,  num:  'PO1', amount: 1000, userId: 1, clientId: 1, description: 'Insurance policy number PO1' },
    {  id:  2,  num:  'PO2', amount: 2000, userId: 1, clientId: 2, description: 'Insurance policy number PO2' },
    {  id:  3,  num:  'PO3', amount: 3000, userId: 1, clientId: 3, description: 'Insurance policy number PO3' },
    {  id:  4,  num:  'PO4', amount: 4000, userId: 1, clientId: 4, description: 'Insurance policy number PO4' }
   ];

   return {policies};

  }
}

As you can see, you override the createDb function to return any data you want your in-memory database to return. Each item should have a unique id.

Next, you need to integrate the in-memory web api module with your application and provide the data service as a parameter for the forRoot() method of the InMemoryWebApiModule module.

Open the src/app/app.module.ts file and provide the data service.

import { InMemoryWebApiModule } from angular-in-memory-web-api;  
import { DataService } from ./data.service;
// [...] 

@NgModule({
  declarations: [
    // [...]
  ],
  imports: [
    // [...]
    InMemoryWebApiModule.forRoot(DataService)
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Thanks to this service, we'll be able get around the absence of a real REST API server during development, by simulating all CRUD actions of an HTTP REST API while our data is stored locally in our frontend application.

Creating your Angular 18 Data CRUD Service

After installing and setting up the in-memory web api module, you next need to create another Angular 18 service with the PolicyService name which encapsulates all the code needed for making CRUD operations to create, read, update and delete insurance policies:

$ ng generate service policy

Open the generated src/app/policy.service.ts file and:

  • Import HttpClient into your service,
  • Add the CRUD methods necessary for working with policies.
import { Injectable } from '@angular/core';
import { HttpClient } from “@angular/common/http;

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

  SERVER_URL: string = "http://localhost:8080/api/";
  constructor(private httpClient: HttpClient) { }

  public getPolicies(){ 
       return this.httpClient.get(this.SERVER_URL + 'policies');
  }

  public getPolicy(policyId){
       return this.httpClient.get(`${this.SERVER_URL + 'policies'}/${policyId}`); 
  }
  public createPolicy(policy: {id: number, amount: number, clientId: number, userId: number, description: string}){
      return this.httpClient.post(`${this.SERVER_URL + 'policies'}`, policy)
  }

  public deletePolicy(policyId){
      return this.httpClient.delete(`${this.SERVER_URL + 'policies'}/${policyId}`)
  }
  public updatePolicy(policy: {id: number, amount: number, clientId: number, userId: number, description: string}){
      return this.httpClient.put(`${this.SERVER_URL + 'policies'}/${policy.id}`, policy)
  }

}

You've added four CRUD methods:

  • getPolicies: for retrieving all insurance policies,
  • getPolicy : for retrieving an insurance policy by id,
  • createPolicy: for creating a new insurance policy,
  • deletePolicy: for deleting an insurance policy by id,
  • updatePolicy: for updating an existing insurance policy.

When you are using the in-memory database, you actually can set the SERVER_URL to any URL. It really doesn't matter as you will not need to use a real API server. In any case, your HTTP requests sent using Angular 18 HttpClient will be all proxied to the in-memory web api.

The Angular http client is an HTTP library that comes pre-built with the Angular framework. This service is accessible as an injectable class, which has methods for sending HTTP requests to the server. When you create a new Angular project, the Angular CLI will automatically add it as a default.

Testing your Angular 18 In-Memory Web API

Now, you can test your CRUD methods in your main application component. Open the existing src/app/app.component.ts file and update it accordingly:

import { Component, OnInit } from '@angular/core';
import { PolicyService } from './policy.service';

@Component({
  selector: 'app-contact-list',
  templateUrl: './contact-list.component.html',
  styleUrls: ['./contact-list.component.css']
})
export class PolicyListComponent implements OnInit {

  policies: any[] = [];
  constructor(private policyService: PolicyService) { }

  ngOnInit() {
    this.policyService.getPolicies().subscribe((data : any[])=>{
        console.log(data);
        this.policies = data;
    })
  }
}

You first declare a policies array which will be used to contain the insurances policies that you can fetch from the in-memory web api. Next, you inject PolicyService and then you make a call to the getPolicies method of the injected instance to get the available insurance policies and put them in the policies array. The getPolicies method will be fired once you component is initialized because you've called it in the ngOnInit life-cycle event.

Next open the src/app/app.component.html file and update it accordingly:

<h1>Insurance Policies with Angular 18 example</h1>
<table style="width:100%">
  <tr>
    <th>Policy Number</th>
    <th>Amount</th>
    <th>Description</th>
    <th>Actions</th>
  </tr>
  <tr *ngFor="let policy of policies" >
    <td>{{ policy.num }}</td>
    <td>{{ policy.amount }}</td>
    <td>{{ policy.description }}</td>

    <td>
    <button (click)="deletePolicy(policy.id)">Delete</button>
    <button (click)="updatePolicy(policy)">Update</button>
    </td>
  </tr>
</table>

You simply go through all the policies using the *ngFor directive and display each policy number, amount and description. And you also add action buttons for calling delete and update operations in each policy table's row.

Next, go back to your application component and add an implementation for .deletePolicy and .updatePolicy methods.

public deletePolicy(policyId){
    this.policyService.deletePolicy(policyId).subscribe((ret)=>{
          console.log("Policy deleted: ", ret);
    })
}


public updatePolicy(policy: {id: number, amount: number, clientId: number, userId: number, description: string}){
    let newPolicy:{id: number, amount: number, clientId: number, userId: number, description: string} = {policy.id, 0, 0, 0};
    this.policyService.updatePolicy(policyId).subscribe((ret)=>{
          console.log("Policy updated: ", ret);
    });
}  

The .updatePolicy method updates any policy with zeros for all the others fields except the id. This of course should be used with a form to get the new data from the user and update accordingly.

You should also add a form and bind its submit event with a createPolicy method that can have the following implementation:

public createPolicy(policy){
    this.policyService.createPolicy(policy).subscribe((ret)=>{
          console.log("Policy created: ", ret);
    });
}

Creating the Angular 18 Components

Now, that both of the in-memory data service and the CRUD service are created, you can proceed to create the components of your Angular 18 application. A component controls a part of your application screen and interacts with different services to fetch and display data.

Head back to your terminal and run the following commands to create components:

$ ng generate component policy-list
$ ng generate component policy-create

The CLI will create two PolicyListComponent and PolicyCreateComponent components and automatically import them into the main application module.

You don't need to create delete and update components since you can use the create component to also update policies and you can call delete operations from the list of policies in the list component.

You can now execute the following command to serve your project and test your Angular 18 web application:

$ ng start

Conclusion

In this article, you've crafted a concise Angular 18 CRUD example application, leveraging the angular-in-memory-web-api module to fabricate a pseudo REST API with an in-memory database. This approach obviates the necessity for a live backend server during the development phase of your front-end project, especially when backend accessibility is limited.

The angular-in-memory-web-api module adeptly intercepts HTTP requests initiated by Angular's HttpClient module, rerouting them to an in-memory data store that you manage directly from your application's frontend. This functionality enables seamless simulation of delayed responses and facilitates nearly all tasks typically expected from a backend developer. However, it's essential to note that this module is not intended for production use due to its inherent limitations.

In essence, the in-memory module serves as a surrogate backend system for your actual backend infrastructure. It intercepts incoming HTTP requests, processes them internally, and subsequently returns the results to the requesting module. When transitioning to a real API backend service in your Angular 18 front-end application, there's no need for modification to your existing API endpoints.

By opting for the in-memory web API module instead of setting up a real database and deploying a full-fledged REST API server for testing purposes, you streamline the development process. This allows your front-end team to progress independently, while the backend team (or you, as a full-stack developer) can focus on completing the backend's design and implementation. Consequently, your pre-existing API endpoints tailored for the Angular 18 front-end application remain unaffected, ensuring seamless integration with the actual backend system.


  • Date: