Angular’s Dependency Injection (DI) system relies heavily on the @Injectable
decorator and the providedIn
property to manage dependencies. These features allow you to define how and where services are provided, making your code more modular and maintainable. In this article, we’ll explore how to use @Injectable
and providedIn
effectively in Angular, including best practices and advanced techniques. By the end of this guide, you’ll have a solid understanding of how to configure and inject services in your Angular applications.
What is @Injectable?
The @Injectable
decorator marks a class as a dependency that can be injected into other classes. It is used to define services, which are reusable classes that provide functionality like data fetching, logging, or authentication. By default, services decorated with @Injectable
are provided in the root injector, making them available throughout the application.
Example: Basic @Injectable Usage
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root',
})
export class DataService {
getData() {
return 'Some data';
}
}
What is ProvidedIn?
The providedIn
property in the @Injectable
decorator specifies where the service should be provided. It can be set to:
- 'root': The service is provided in the root injector and is available throughout the application.
- 'any': The service is provided in all modules, including lazy-loaded modules.
- A specific module: The service is provided in a specific module and is only available to components in that module.
Example: Providing a Service in a Specific Module
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'my-module',
})
export class DataService {
getData() {
return 'Some data';
}
}
Benefits of Using ProvidedIn
Using providedIn
offers several benefits:
- Tree Shaking: Services provided with
providedIn: 'root'
can be tree-shaken, meaning they are only included in the final bundle if they are used. - Modularity: Services can be scoped to specific modules, reducing the risk of unintended side effects.
- Simplicity:
providedIn
eliminates the need to add services to theproviders
array in modules or components.
Advanced Techniques
1. Lazy Loading with ProvidedIn
When a service is provided in a lazy-loaded module, it is only instantiated when the module is loaded. This can improve performance by reducing the initial bundle size.
@Injectable({
providedIn: 'lazy-module',
})
export class DataService {}
2. Optional Dependencies
Use the @Optional
decorator to mark a dependency as optional:
import { Optional } from '@angular/core';
constructor(@Optional() private dataService: DataService) {}
Secrets and Hidden Facts
- Singleton Services: Services provided in the root injector are singletons, meaning only one instance is created and shared across the application.
- Circular Dependencies: Avoid circular dependencies by refactoring your code or using forwardRef.
- Custom Injectors: You can create custom injectors to provide services in specific contexts.
Conclusion
The @Injectable
decorator and providedIn
property are essential tools for managing dependencies in Angular. By understanding how to use them effectively, you can create modular, maintainable, and scalable applications. Whether you’re working with singleton services or module-specific instances, these features are key to mastering Angular’s Dependency Injection system.
So, start using @Injectable
and providedIn
in your projects and unlock the full potential of Angular!

No comments: