How to useValue, useClass, useExisting and useFactory in Angular

Introduction: Angular’s dependency injection (DI) system plays a crucial role in building scalable and maintainable applications. Understanding DI providers is essential for effective Angular development.

Understanding Angular Dependency Injection Providers: Angular provides several DI providers to configure how dependencies are injected into components, services, and other Angular constructs. The main providers are useValue, useClass, useExisting, and useFactory. Each provider offers unique capabilities to handle different scenarios.

1. useValue: The useValue provider allows injecting a simple value into Angular components or services. It’s useful for injecting constants, configuration objects, or any other value.

Example:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class AppConfig {
  apiUrl = 'https://api.example.com';
}

// In AppModule providers:
providers: [{ provide: AppConfig, useValue: { apiUrl: 'https://api.example.com' } }]

2. useClass: The useClass provider injects an instance of a class. It’s helpful for injecting services with multiple implementations or when custom initialization is required.

Example:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class LoggerService {
  log(message: string) {
    console.log(message);
  }
}

@Injectable({
  providedIn: 'root',
})
export class DebugLoggerService extends LoggerService {
  log(message: string) {
    console.debug(message);
  }
}

// In AppModule providers:
providers: [{ provide: LoggerService, useClass: DebugLoggerService }]

3. useExisting: The useExisting provider allows using an existing token as an alias. It’s useful for creating aliases or providing multiple tokens for the same service.

Example:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class OldLoggerService {
  log(message: string) {
    console.log(message);
  }
}

@Injectable({
  providedIn: 'root',
})
export class NewLoggerService {
  log(message: string) {
    console.log(message);
  }
}

// In AppModule providers:
providers: [
  OldLoggerService,
  { provide: NewLoggerService, useExisting: OldLoggerService }
]

4. useFactory: The useFactory provider creates a dependency using a factory function. It’s useful for lazy-loading modules, creating dependencies dynamically, or performing complex initialization.

Example:

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root',
})
export class AuthService {
  getToken() {
    // Simulate token retrieval
    return 'fakeToken';
  }
}

// In AppModule providers:
providers: [
  {
    provide: AuthService,
    useFactory: () => {
      // Custom initialization logic
      const authService = new AuthService();
      authService.configure();
      return authService;
    },
  },
]

Conclusion: Understanding Angular’s dependency injection providers is crucial for building robust Angular applications. By mastering these providers and knowing when to use each, developers can effectively manage dependencies and create maintainable codebases.

Next Post Previous Post
No Comment
Add Comment
comment url