In-Memory-Web-API in Angular Standalone

By Arvind Rai, March 15, 2024
On this page we will learn to create our Angular application using in-memory-web-api. In development phase of application using HTTP operations, we developers need dummy REST API to test application. Angular provides in-memory-web-api that creates dummy DB with our seed data. When we insert and update data in this DB, the changes take place only in memory.
Here I will create a standalone application using in-memory-web-api step-by-step.

1. Install In Memory Web API

To work with in-memory-web-api, we need to install it if already not installed. Use the below command.
npm i angular-in-memory-web-api 
The above command will install latest version of angular-in-memory-web-api. To check if this api is alraedy installed or not, check the package.json for below line.
 "dependencies": {
  	------
    "angular-in-memory-web-api": "^0.17.0",
 }
Version can vary with Angular version.

2. Create Class with InMemoryDbService

Create a class in your application implementing InMemoryDbService and define createDb() method.
inmemory-test-data.ts
import { InMemoryDbService } from 'angular-in-memory-web-api';

export class InmemoryTestData implements InMemoryDbService {
  createDb() {
    let bookDetails = [
      { id: 11, name: 'Spring Boot by Krishn', category: 'Spring' },
      { id: 12, name: 'Java Expert by James', category: 'Java' }
    ];
    let writerDetails = [
      { id: '100', name: 'Krishn', city: 'Varanasi' },
      { id: '101', name: 'James', city: 'Mumbai' }
    ];
    return { books: bookDetails, writers: writerDetails };
  }
} 
Define the data structure with some dummy data and return the object containing path to access data. We need to prefix /api/ to create URL to access these data.
The DB given above, creates following paths.
/api/books
/api/writers 
We can perform CRUD operations on books and writers using above paths.

3. importProvidersFrom()

importProvidersFrom() collects providers from all specified NgModule . The importProvidersFrom() is used in application injector or another environment injector but not in component providers. We can use importProvidersFrom() with bootstrapApplication and with providers field of Route in route configuration.
To enable in-memory-web-api in standalone application, use importProvidersFrom() as below.
app.config.ts
import { ApplicationConfig, importProvidersFrom } from '@angular/core';
import { provideHttpClient } from '@angular/common/http';
import { InMemoryWebApiModule } from 'angular-in-memory-web-api';
import { InmemoryTestData } from './inmemory-test-data';

export const APP_CONFIG: ApplicationConfig = {
  providers: [
    provideHttpClient(),
    importProvidersFrom(InMemoryWebApiModule.forRoot(InmemoryTestData))
  ]
}; 
provideHttpClient() makes HttpClient available for dependency injection.

4. Delaying Response

In some cases we may need to test application when REST API is returning response with some delay. To enable this delay in our dummy DB, configure delay in milliseconds as below.
export const APP_CONFIG: ApplicationConfig = {
  providers: [
    provideHttpClient(),
    importProvidersFrom(InMemoryWebApiModule.forRoot(InmemoryTestData, {delay: 2000}))
  ]
}; 
The configuration {delay: 2000} will delay response by 2 seconds.

5. HTTP Operations

In my demo application, I performing HTTP operations for POST and GET methods. To test application with dummy data, we just need to use our dummy REST API URLs.
book.service.ts
import { Injectable } from '@angular/core';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Book } from '../book';

@Injectable({
    providedIn: 'root'
})
export class BookService {
    constructor(private http: HttpClient) { }
    saveBook(book: Book): Observable<Book[]> {
        console.log(book);
        return this.http.post<Book[]>("/api/books", book);
    }
    findBookByCategory(category: string): Observable<Book[]> {
        const httpParams = new HttpParams().set('category', category);
        return this.http.get<Book[]>("/api/books", {
            params: httpParams
        });
    }
    findWriterByCity(city: string): Observable<Book[]> {
        const httpParams = new HttpParams().set('city', city);
        return this.http.get<any[]>("/api/writers", {
            params: httpParams
        });
    }
} 
book.component.ts
import { Component, OnInit } from '@angular/core';
import { Observable } from 'rxjs';
import { BookService } from './services/book.service';
import { Book } from './book';
import { CommonModule } from '@angular/common';

@Component({
   selector: 'app-book',
   standalone: true,
   imports: [CommonModule],
   templateUrl: './book.component.html'
})
export class BookComponent implements OnInit {
   booksById$!: Observable<Book[]>;
   booksByCategory$!: Observable<Book[]>;
   writersByCity$!: Observable<any[]>;

   constructor(private bookService: BookService) { }

   ngOnInit() {
      this.addBook();
      this.searchBookByCategory('Spring');
      this.searchWriterByCity("Mumbai");
   }
   addBook() {
      const book: Book = { id: 13, name: 'Spring Data by Neeraj', category: 'Spring' };
      const data = this.bookService.saveBook(book);
      console.log(data);
   }
   searchBookByCategory(category: string) {
      this.booksByCategory$ = this.bookService.findBookByCategory(category);
   }
   searchWriterByCity(city: string) {
      this.writersByCity$ = this.bookService.findWriterByCity(city);
   }
} 
book.component.html
<h3>Books By Category</h3>
<div *ngFor="let book of booksByCategory$ | async" >
    Id: {{book.id}}, Name: {{book.name}}, Category: {{book.category}}
</div>

<h3>Writers By City</h3>
<div *ngFor="let writer of writersByCity$ | async" >
    Id: {{writer.id}}, Name: {{writer.name}}, City: {{writer.city}}
</div> 

6. Reference

POSTED BY
ARVIND RAI
ARVIND RAI
LEARN MORE








©2024 concretepage.com | Privacy Policy | Contact Us