Introduction

Modern web applications rarely work in isolation. Almost every real application communicates with a backend to fetch, create, update, or delete data.

In Angular, the recommended way to interact with APIs is by using services, and the built-in HttpClient module makes performing HTTP operations simple and consistent.

In this article, we will learn step by step how to create a reusable Angular service to handle API calls, including:

Real-World Scenario

Imagine you are building a small product management module. You need operations like:

If you implement API calls directly inside multiple components, your project quickly becomes difficult to manage.

Instead, you create a single Angular service called ProductService that handles all API operations in one place. This makes your project clean, scalable, and easier to maintain.

Step 1: Enable HttpClient in Angular

Open app.module.ts and import HttpClientModule:

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

@NgModule({
  imports: [BrowserModule, HttpClientModule],
})
export class AppModule {}

Step 2: Generate a Service

Run the following command:

Code
ng generate service services/product

Angular generates a file named:

product.service.ts

Step 3: Create the Service With API Methods

Example API URL:

https://localhost:5000/api/products

Service code

Code
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

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

  private apiUrl = 'https://localhost:5000/api/products';

  constructor(private http: HttpClient) {}

  getProducts(): Observable<any> {
    return this.http.get(this.apiUrl);
  }

  getProductById(id: number): Observable<any> {
    return this.http.get(`${this.apiUrl}/${id}`);
  }

  addProduct(product: any): Observable<any> {
    return this.http.post(this.apiUrl, product);
  }

  updateProduct(id: number, product: any): Observable<any> {
    return this.http.put(`${this.apiUrl}/${id}`, product);
  }

  deleteProduct(id: number): Observable<any> {
    return this.http.delete(`${this.apiUrl}/${id}`);
  }
}

Step 4: Use the Service in a Component

Example: Show products in UI.

Code
import { Component, OnInit } from '@angular/core';
import { ProductService } from '../services/product.service';

@Component({
  selector: 'app-products',
  templateUrl: './products.component.html'
})
export class ProductsComponent implements OnInit {

  products: any[] = [];

  constructor(private productService: ProductService) {}

  ngOnInit(): void {
    this.productService.getProducts().subscribe(data => {
      this.products = data;
    });
  }
}

Component Template

Code
<h2>Product List</h2>

<ul>
  <li *ngFor="let product of products">
    {{ product.name }} - Rs. {{ product.price }}
  </li>
</ul>

Handling API Errors

Add RxJS catchError in service:

Code
import { throwError } from 'rxjs';
import { catchError } from 'rxjs/operators';

getProducts(): Observable<any> {
  return this.http.get(this.apiUrl).pipe(
    catchError(error => {
      console.error('Error fetching products:', error);
      return throwError(() => error);
    })
  );
}

Using a Loading Indicator

You can manage component UI state:

Code
loading = true;
errorMessage = '';

ngOnInit() {
  this.productService.getProducts().subscribe({
    next: (data) => {
      this.products = data;
      this.loading = false;
    },
    error: (err) => {
      this.errorMessage = 'Failed to load products';
      this.loading = false;
    }
  });
}

Example Template With UI Feedback

Code
<p *ngIf="loading">Loading...</p>
<p *ngIf="errorMessage">{{ errorMessage }}</p>

<ul *ngIf="!loading && !errorMessage">
  <li *ngFor="let product of products">
    {{ product.name }}
  </li>
</ul>

Workflow Diagram

Code
Component Requests Data
        |
        v
 Angular Service Calls API
        |
        v
 HttpClient Sends Request
        |
        v
 API Response Received
        |
        v
 Component Updates UI

Flowchart

Code
START|
  v
Call Service Method|
  v
Send API Request via HttpClient
  |+--- Error? ---> Display Error Message|
  v
Update UI with Data
  |
 END

Best Practices

Common Mistakes and Solutions

MistakeWhy it HappensSolution
HttpClient not workingModule not importedAdd HttpClientModule
Values not showingForgetting subscribeAlways call .subscribe()
Duplicate codeMaking API calls in multiple componentsUse a shared service

Conclusion

Angular services allow you to create reusable and scalable logic for API access. With HttpClient, making requests becomes clean and efficient. Once this concept is mastered, you can move into:

This is the foundation for a professional Angular application.