AI Reading
Quick summary of this article
Angular services are reusable classes that handle business logic, API calls, and data sharing, separate from UI components. Dependency Injection (DI) is the pattern Angular uses to deliver these services efficiently. Services are created with the @Injectable() decorator and can be provided app-wide or limited to specific components.
- Services encapsulate logic like HTTP calls, data persistence, logging, or authentication, keeping components focused on the view.
- The
@Injectable({ providedIn: 'root' })decorator registers a service in the root injector, making it a single shared instance across the app. - Inject services into components via the constructor, for example
constructor(private userService: UserService). - Services can have local scope by listing them in a component's
providersarray, creating a new instance just for that component and its children. - Best practices include using services for non-UI logic, preferring
providedIn: 'root'for stateless services, and using constructor injection.
Chapter 7: Services and Dependency Injection in Angular
Angular services allow you to organize and share business logic, API communication, and reusable data across components. Dependency Injection (DI) is the design pattern Angular uses to deliver these services efficiently and modularly.
What is a Service in Angular?
A service is a reusable class that encapsulates logic not directly related to views or UI. Common use cases include HTTP calls, data persistence, and utilities like logging or authentication.
Creating a Service
Using Angular CLI
ng generate service user
This command creates user.service.ts with a boilerplate structure and the @Injectable() decorator.
Using the @Injectable() Decorator
The @Injectable() decorator marks a class as available to be injected as a dependency. Here’s an example:
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class UserService {
getUsers() {
return ['John', 'Jane', 'Doe'];
}
}
The providedIn: 'root' syntax automatically registers this service in the application’s root injector, making it app-wide.
Injecting Services into Components
To use a service, inject it into a component’s constructor:
import { Component } from '@angular/core';
import { UserService } from './user.service';
@Component({
selector: 'app-user-list',
template: `
<ul>
<li *ngFor="let user of users">{{ user }}</li>
</ul>
`
})
export class UserListComponent {
users: string[] = [];
constructor(private userService: UserService) {
this.users = this.userService.getUsers();
}
}
Service Scope: App-wide vs Local
1. App-wide (Global) Scope
When you provide a service in the root injector (with providedIn: 'root'), it is available throughout the app, and a single instance is shared:
@Injectable({
providedIn: 'root'
})
export class LoggerService { ... }
2. Local Scope (Component-level)
You can provide a service only to a specific component and its children by declaring it in the component’s providers array:
@Component({
selector: 'app-local',
templateUrl: './local.component.html',
providers: [LocalService]
})
export class LocalComponent { ... }
This creates a new instance of the service for that component only, ideal for isolating state or behavior.
Best Practices
- Use services for business logic and data access, not UI code.
- Prefer
providedIn: 'root'for stateless services to avoid manual registration. - Inject services via constructor injection to leverage Angular’s DI system.
- Avoid creating multiple instances of the same service unless necessary (e.g., component-specific state).
Conclusion
Services and Dependency Injection are core to scalable Angular applications. They separate logic from UI, reduce redundancy, and promote modular architecture. Whether used globally or locally, services empower your app to stay clean and maintainable.
Next Steps
In Chapter 8, we’ll dive into HTTP communication in Angular, including how to use the HttpClient module to make API requests and handle responses with Observables.
