Angular 12 Service Example – Http CRUD Operations

In this Angular tutorial, we are going to discuss Angular Services.  In the Angular Service example tutorial, we will create a Service to perform CRUD (Create, Read, Update and Delete) operations using the HttpClient Angular service.

Services help up managing functions and methods which can be consumed by other components or modules throughout the application. Ideally, use Services to perform network data communications and error handling in an application.

Responsibilities of Angular Service Class

  • Makes application more organized by keeping reusable methods at one place.
  • Makes application easy to maintain and test.
  • We can share data between multiple components which are not in direct relation.
  • Handling of common operations like CRUD operations, application authentication, creating Auth Guards.
  • For keeping simple common methods at one place like date conversion, string formatting, returning boolean expressions etc.

 

Let’s begin with our example tutorial

Install Angular CLI

To start with the Angular project, first you need to install the latest version of Angular CLI.

$ npm install -g @angular/cli@latest

 

Create New Angular Project

After that, run the following ng command to create a new project.

$ ng new angular-service-app
? Would you like to add Angular routing? Yes
? Which stylesheet format would you like to use? SCSS

Get inside the project directory

$ cd angular-service-app

Run the application

$ ng serve --open

The --open flag will open the application in the browser

Create New Angular Service

Next, we will create a new Angular service class that will perform CRUD operations for our demo ToDO application. Create a service by executing the below ng generate command.

$ ng generate service crud-http

This will create the crud-http.service.ts service with a spec file under the app folder

The crud-http.service.ts file will have the following auto-generated content.

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

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

  constructor() { }
}

The @Injectable() decorator enables a simple Angular class to be provided and get injected as a dependency wherever required.

By default when we create a service the providedIn is set to 'root' which provides the services available throughout the application without even providing it inside the App Module.  You can check more details on limiting the Service Provider scope here.

 

Import HttpClientModule in App Module

To use HttpClient class methods, first we need to import the HttpClientModule in the AppModule which is the main module.

Open the app.module.ts file, them update the imports array as shown below:

// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';

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

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

Now we are ready to update our CrudHttpService with CRUD methods.

 

Setup Mock JSON Server

We can easily set up a local mock server by installing the json-server package. This will help up to quickly test our application performing CRUD operations by using a JSON file.

Step 1) Install json-server

Run the npm command to install the json-server package globally.

$ npm install -g json-server

Step 2) Create a json file

Next, create a data.json file inside the app/data.json  this file will keep the data that will be used for CRUD operations.

Add following property in data.json file

{
    "todos":[]
}

Step 3) Start mock server

Finally run the mock server in new CLI instance with json file specified using below command

$ json-server --watch ./src/app/data.json

  \{^_^}/ hi!

  Loading ./src/app/data.json
  Done

  Resources
  http://localhost:3000/todos

  Home
  http://localhost:3000

  Type s + enter at any time to create a snapshot of the database
  Watching...

Following are the API URLs that will be available on our server:

  • GET /todos – fetch all todos
  • GET /todos/: id – fetch a single todo detail by id
  • POST /todos – create a new todo
  • PUT /todos/: id – update a todo by id
  • PATCH /todos/: id – partially update a todo by id
  • DELETE /todos/:id – delete a todo by id

 

CRUD Method in Service Class

Open the crud-http.service.ts file, then update it with the following code

// crud-http.service.ts
import { HttpClient, HttpErrorResponse, HttpHeaders } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { catchError } from 'rxjs/operators';
import { Observable, throwError } from 'rxjs';

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

  apiUrl: string = 'http://localhost:3000/todos';
  headers = new HttpHeaders().set('Content-Type', 'application/json');

  constructor(private http: HttpClient) { }

  // Create
  create(data: any): Observable<any> {
    let API_URL = `${this.apiUrl}`;
    return this.http.post(API_URL, data)
      .pipe(
        catchError(this.handleError)
      )
  }

  // Read
  list() {
    return this.http.get(`${this.apiUrl}`);
  }

  // Update
  update(id: any, data: any): Observable<any> {
    let API_URL = `${this.apiUrl}/${id}`;
    return this.http.put(API_URL, data, { headers: this.headers }).pipe(
      catchError(this.handleError)
    )
  }

  // Delete
  delete(id: any): Observable<any> {
    var API_URL = `${this.apiUrl}/${id}`;
    return this.http.delete(API_URL).pipe(
      catchError(this.handleError)
    )
  }

  // Handle API errors
  handleError(error: HttpErrorResponse) {
    if (error.error instanceof ErrorEvent) {
      console.error('An error occurred:', error.error.message);
    } else {
      console.error(
        `Backend returned code ${error.status}, ` +
        `body was: ${error.error}`);
    }
    return throwError(
      'Something bad happened; please try again later.');
  };

}

 

Consum Service and CRUD Methods in Component

For accessing the Service methods, import the CrudHttpService service class in constructor of component file app.component.ts

// app.component.ts
import { Component } from '@angular/core';
import { CrudHttpService } from './crud-http.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {

  constructor(private crudHttpService: CrudHttpService){}

}

Now, we can call our CrudHttpService methods. The listTodo() method will be called inside the ngOnInit() hook to show all todo’s by calling the list() service method.

Similerly we have other methods to create, delete, edit or update todo’s in component, which eventually calling our reusable service methods.

import { Component } from '@angular/core';
import { CrudHttpService } from './crud-http.service';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  title = 'angular-service-app';

  todoList:any = [];

  constructor(private crudHttpService: CrudHttpService){}

  ngOnInit(): void {
    this.listTodos();
  }

  listTodos(){
    this.crudHttpService.list().subscribe((response)=>{
      this.todoList = response;
    },(error=>{

    }));
  }

  createTodo(){
    let todo = {
      id: new Date().getTime(),
      title:`Some Todo` 
    }
    this.crudHttpService.create(todo).subscribe((response)=>{
      this.listTodos();
    },(error=>{

    }));
  }

  editTodo(todo: any){
    let data = {
      id: new Date().getTime(),
      title:`Some Todo` 
    }
    this.crudHttpService.update(todo.id,data).subscribe((response)=>{
      this.listTodos();
    },(error=>{

    }));
  }

  deleteTodo(id: any){
    this.crudHttpService.delete(id).subscribe((response)=>{
      this.listTodos();
    },(error=>{
    }));
  }
}

Show the list with action buttons update the app.component.html template with following code.

<div class="container">
  <table class="table">
    <thead>
      <tr>
        <th>ID</th>
        <th>Title</th>
        <th>Actions</th>
      </tr>
    </thead>
    <tbody>
      <tr *ngFor="let todo of todoList">
        <td>{{todo.id}}</td>
        <td>{{todo.title}}</td>
        <td>
          <button type="button" class="btn btn-link" (click)="editTodo(todo)">Edit</button>
          <button type="button" class="btn btn-link" (click)="deleteTodo(todo.id)">Delete</button>
        </td>
      </tr>
    </tbody>
  </table>
  <button type="button" class="btn btn-success" (click)="createTodo()">Create</button>
</div>

Now, run application by hitting $ ng serve --open or $ npm start 

 

 

Conclusion

To sum up, we are completed with our Angular Service tutorial. Where we discussed how to create a Service class, then use it to perform CRUD HTTP operations on server data. Although we set up a Mock server using the json-server, which proves a good tool to replicate real scenarios. But, in a real application, we can simply replace our mock services very easily.

 

Leave a Comment

Your email address will not be published. Required fields are marked *