Topic 8: Services (with 3 usage) and Dependency Injection

Github project link – https://github.com/kuldeep101990/angular-step8

In this step, we’ll explore Angular services, which allow you to share data, methods, or functionality across components. For Java developers, this is similar to using service classes in Java to manage business logic, data access, and shared functionality.


What is a Service in Angular?

A Service in Angular is a class that provides reusable functionality and manages shared state or business logic. This is akin to a service layer in Java, where you encapsulate business logic, data access, or utility methods for reuse across controllers or other components.


Why Use Services in Angular?

  1. Sharing Data Between Components:
    Angular services allow data sharing across unrelated components, similar to a shared service layer in Java that provides common functionality to multiple controllers.
  2. Separation of Concerns:
    Services help decouple business logic from components, just like Java service classes separate data access logic from the presentation layer in frameworks like Spring MVC.
  3. Centralized API Management:
    Services in Angular can handle external API calls, comparable to how Java service classes manage API interactions using libraries like RestTemplate.

How to Create a Service in Angular

To create a service in Angular, use the @Injectable decorator, which makes the service injectable into other components or services. This is similar to using @Service or @Component annotations in Java to enable dependency injection.


Example: Data Service

Angular:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
  providedIn: 'root', // Automatically registers the service at the root level
})
export class DataService {
  constructor(private http: HttpClient) {}
  getData() {
    return this.http.get('https://api.example.com/data');
  }
}

Java Comparison:

import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class DataService {
    private final RestTemplate restTemplate;
    public DataService(RestTemplate restTemplate) {
        this.restTemplate = restTemplate;
    }
    public Object getData() {
        return restTemplate.getForObject("https://api.example.com/data", Object.class);
    }
}

In both cases, the service is a centralized point for fetching data, encapsulating the HTTP call logic.


How to Use a Service in Angular

To use a service, inject it into a component’s constructor. This is similar to dependency injection in Java with the @Autowired annotation.

Example: Injecting the Service

Angular:

import { Component, OnInit } from '@angular/core';
import { DataService } from './data.service';
@Component({
  selector: 'app-data',
  template: `
    <ul>
      <li *ngFor="let item of data">{{ item }}</li>
    </ul>
  `,
})
export class DataComponent implements OnInit {
  data: any[];
  constructor(private dataService: DataService) {}
  ngOnInit() {
    this.dataService.getData().subscribe(data => {
      this.data = data;
    });
  }
}

Java Comparison:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class DataComponent {
    private final DataService dataService;
    @Autowired
    public DataComponent(DataService dataService) {
        this.dataService = dataService;
    }
    public void loadData() {
        Object data = dataService.getData();
        // Process data
    }
}

Both examples demonstrate how to inject a service into a component and use it to fetch or process data.


Singleton Services and Dependency Injection

Angular services, by default, are singletons when registered at the root level (using providedIn: 'root'). This ensures that the same instance of the service is shared across the application, just like Spring-managed singleton beans in Java.

In earlier Angular versions (prior to Angular 6), you needed to manually register services in the providers array of an NgModule, similar to configuring beans in older Java applications using XML.


Shared Services for Component Communication

Shared services in Angular can be used to facilitate communication between components that don’t share a direct relationship, such as sibling components.

Example:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
  providedIn: 'root',
})
export class SharedService {
  private messageSource = new BehaviorSubject<string>('default message');
  currentMessage = this.messageSource.asObservable();
  changeMessage(message: string) {
    this.messageSource.next(message);
  }
}

Java Comparison:

In Java, you might use a shared service or a utility class to manage shared state:

import org.springframework.stereotype.Service;
@Service
public class SharedService {
    private String message = "default message";
    public String getMessage() {
        return message;
    }
    public void setMessage(String message) {
        this.message = message;
    }
}


Major Version Differences

  1. Angular 5:
    • Services needed to be explicitly registered in the providers array of the @NgModule.
    • Java Comparison: Similar to manually configuring beans in XML in older Spring versions.
  2. Angular 6+:
    • Introduced the providedIn property in the @Injectable decorator, which allows services to be automatically registered at the root level or feature module level.
    • Java Comparison: Similar to Spring Boot’s @ComponentScan or Java-based configuration that simplifies bean registration.

Conclusion

Services in Angular play a critical role in managing shared data, business logic, and API interactions, much like the service layer in Java. They enhance modularity, maintainability, and testability in your application. By leveraging Angular’s dependency injection system, you can design robust applications that are easy to extend and maintain—just as you would in a well-architected Java application.

For Java developers, the concept of Angular services will feel intuitive, bridging familiar patterns like service layers and dependency injection into the modern world of front-end development.


Leave a Reply

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