Dependency Injection (DI) is a foundational concept in Angular, designed to streamline dependency management and ensure clean, modular code. For developers aiming to excel in interviews, a thorough understanding of DI is essential, as it often features in Angular interview questions. This guide breaks down Angular’s DI system, highlights common pitfalls, and offers strategies for confidently explaining it during an interview.
Dependency Injection is a design pattern where dependencies are provided to a class rather than being instantiated by the class itself. This separation of concerns promotes loose coupling, making applications easier to maintain and test.
Analogy:
Imagine a restaurant (component) that needs ingredients (dependencies). Instead of sourcing the ingredients, the restaurant receives them from suppliers (Injector). This setup allows the restaurant to focus on cooking while making it easy to switch suppliers if needed.
Angular’s DI system revolves around three key concepts: providers, injectors, and tokens.
A provider tells Angular how to create and deliver an instance of a dependency. Providers are registered at various levels (e.g., root, module, or component) to control the service’s scope.
typescript@Injectable({
providedIn: 'root',
})
export class NotificationService {
notify(message: string) {
console.log(`Notification: ${message}`);
}
}
Here, providedIn: 'root'
ensures the NotificationService
is a singleton available throughout the application.
The injector maintains a registry of providers and creates dependencies as needed. When a class requests a dependency, the injector delivers the instance.
Tokens act as unique identifiers for providers. Angular uses class types as tokens by default, but custom tokens can be created using InjectionToken
when needed.
A service provided at the root level (providedIn: 'root'
) is a singleton shared across the entire application.
Services can be scoped to a specific module by including them in the module’s providers
array.
typescript@NgModule({
providers: [UserService],
})
export class UserModule {}
This ensures the UserService
is only accessible to components within the UserModule
.
Providing a service at the component level creates a new instance for that component and its children.
typescript@Component({
selector: 'app-dashboard',
providers: [DashboardService],
})
export class DashboardComponent {}
This approach isolates the service to the component hierarchy, preventing unintended sharing of data or functionality.
@Injectable()
decorator?@Injectable()
decorator marks a class as injectable, allowing Angular to create and manage its instances.InjectionToken
in Angular?InjectionToken
for injecting non-class dependencies like configuration objects or primitive values.Generate a service using Angular CLI:
bashng generate service data
Decorate the service with @Injectable()
to integrate it into Angular’s DI system:
typescript@Injectable({
providedIn: 'root',
})
export class DataService {
fetchData() {
return 'Sample data from DataService';
}
}
Inject the service into a component:
typescript@Component({
selector: 'app-example',
template: `<p>{{ data }}</p>`,
})
export class ExampleComponent {
data: string;
constructor(private dataService: DataService) {
this.data = this.dataService.fetchData();
}
}
Angular supports multiple providers for the same token using the multi
property.
typescriptconst LOGGER_TOKEN = new InjectionToken<string[]>('Logger');
@NgModule({
providers: [
{ provide: LOGGER_TOKEN, useValue: 'ConsoleLogger', multi: true },
{ provide: LOGGER_TOKEN, useValue: 'FileLogger', multi: true },
],
})
export class AppModule {}
Use InjectionToken
to inject primitive values or objects.
typescriptexport const API_URL = new InjectionToken<string>('apiUrl');
@NgModule({
providers: [{ provide: API_URL, useValue: 'https://api.example.com' }],
})
export class AppModule {}
@Injectable()
Decorator:Angular’s Dependency Injection system is a powerful tool that simplifies dependency management while promoting code reusability and scalability. A solid understanding of DI can significantly boost your confidence and performance in interviews, especially when tackling Angular interview questions. By mastering the fundamentals, practicing implementation, and preparing for advanced scenarios, you’ll be well-equipped to impress interviewers and excel in your Angular development journey.Good luck with your Angular interview preparation!