> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/angular/angular/llms.txt
> Use this file to discover all available pages before exploring further.

# Dependency Injection

> Understanding Angular's dependency injection system, providers, and the inject() function

Dependency Injection (DI) is a design pattern and core feature of Angular that allows you to declare dependencies in your classes rather than creating instances yourself. Angular's DI system handles the creation and lifecycle of service instances.

## Why Dependency Injection?

<CardGroup cols={2}>
  <Card title="Loose Coupling" icon="link-slash">
    Components don't need to know how to create dependencies
  </Card>

  <Card title="Testability" icon="flask">
    Easy to provide mock dependencies for testing
  </Card>

  <Card title="Reusability" icon="recycle">
    Services can be shared across components
  </Card>

  <Card title="Maintainability" icon="wrench">
    Change implementations without modifying consumers
  </Card>
</CardGroup>

## The @Injectable Decorator

Mark a class as available for injection:

```typescript theme={null}
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class DataService {
  private data: string[] = [];

  getData(): string[] {
    return this.data;
  }

  addData(item: string): void {
    this.data.push(item);
  }
}
```

<Note>
  `providedIn: 'root'` makes the service available throughout the application as a singleton.
</Note>

## Provider Scopes

Angular supports several scopes for providing services:

### Root Scope

Application-wide singleton:

```typescript theme={null}
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root'
})
export class UserService {
  private currentUser: User | null = null;

  login(user: User): void {
    this.currentUser = user;
  }

  logout(): void {
    this.currentUser = null;
  }

  getCurrentUser(): User | null {
    return this.currentUser;
  }
}
```

### Component Scope

Provide a service at the component level:

```typescript theme={null}
import { Component } from '@angular/core';
import { LoggerService } from './logger.service';

@Component({
  selector: 'app-user-profile',
  standalone: true,
  providers: [LoggerService], // New instance for this component
  template: `<div>{{ user.name }}</div>`
})
export class UserProfileComponent {
  constructor(private logger: LoggerService) {
    this.logger.log('Component initialized');
  }
}
```

### Platform Scope

Shared across multiple Angular applications on the same page:

```typescript theme={null}
import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'platform'
})
export class PlatformConfigService {
  getConfig() {
    return { apiUrl: 'https://api.example.com' };
  }
}
```

## Using inject() Function

The modern way to inject dependencies:

```typescript theme={null}
import { Component, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { UserService } from './user.service';

@Component({
  selector: 'app-dashboard',
  standalone: true,
  template: `
    <h1>Dashboard</h1>
    <div>{{ user?.name }}</div>
  `
})
export class DashboardComponent {
  // Modern inject() function
  private http = inject(HttpClient);
  private userService = inject(UserService);
  
  user = this.userService.getCurrentUser();

  ngOnInit() {
    this.http.get('/api/data').subscribe(data => {
      console.log('Data loaded:', data);
    });
  }
}
```

<Warning>
  `inject()` can only be called during the construction phase (in constructors, initializers, or factory functions).
</Warning>

## Constructor Injection (Legacy)

Traditional approach using constructor parameters:

```typescript theme={null}
import { Component } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { UserService } from './user.service';

@Component({
  selector: 'app-legacy',
  standalone: true,
  template: `<div>Legacy component</div>`
})
export class LegacyComponent {
  constructor(
    private http: HttpClient,
    private userService: UserService
  ) {
    // Dependencies are injected
  }
}
```

## Injection Tokens

Provide non-class dependencies:

```typescript theme={null}
import { InjectionToken, inject } from '@angular/core';

// Define a token
export const API_URL = new InjectionToken<string>('API URL');

// Provide the token
import { ApplicationConfig } from '@angular/core';

export const appConfig: ApplicationConfig = {
  providers: [
    { provide: API_URL, useValue: 'https://api.example.com' }
  ]
};

// Inject the token
import { Component } from '@angular/core';

@Component({
  selector: 'app-api-consumer',
  standalone: true,
  template: `<div>API: {{ apiUrl }}</div>`
})
export class ApiConsumerComponent {
  apiUrl = inject(API_URL);
}
```

## Provider Types

Angular supports several provider configurations:

### Class Provider

```typescript theme={null}
import { Injectable } from '@angular/core';

export abstract class Logger {
  abstract log(message: string): void;
}

@Injectable()
export class ConsoleLogger implements Logger {
  log(message: string): void {
    console.log(message);
  }
}

// Provide using useClass
import { ApplicationConfig } from '@angular/core';

export const appConfig: ApplicationConfig = {
  providers: [
    { provide: Logger, useClass: ConsoleLogger }
  ]
};
```

### Value Provider

```typescript theme={null}
interface AppConfig {
  apiEndpoint: string;
  production: boolean;
}

const CONFIG: AppConfig = {
  apiEndpoint: 'https://api.example.com',
  production: false
};

export const APP_CONFIG = new InjectionToken<AppConfig>('app.config');

// Provide using useValue
export const appConfig: ApplicationConfig = {
  providers: [
    { provide: APP_CONFIG, useValue: CONFIG }
  ]
};
```

### Factory Provider

```typescript theme={null}
import { inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';

export class ApiService {
  constructor(private http: HttpClient, private baseUrl: string) {}
}

function apiServiceFactory(): ApiService {
  const http = inject(HttpClient);
  const config = inject(APP_CONFIG);
  return new ApiService(http, config.apiEndpoint);
}

// Provide using useFactory
export const appConfig: ApplicationConfig = {
  providers: [
    { provide: ApiService, useFactory: apiServiceFactory }
  ]
};
```

### Existing Provider

Alias one token to another:

```typescript theme={null}
@Injectable({ providedIn: 'root' })
export class NewService {
  getData() { return ['new', 'data']; }
}

export abstract class OldService {
  abstract getData(): string[];
}

// Alias OldService to NewService
export const appConfig: ApplicationConfig = {
  providers: [
    NewService,
    { provide: OldService, useExisting: NewService }
  ]
};
```

## Optional Dependencies

Handle missing dependencies gracefully:

```typescript theme={null}
import { Component, inject, Optional } from '@angular/core';
import { LoggerService } from './logger.service';

@Component({
  selector: 'app-flexible',
  standalone: true,
  template: `<div>Flexible component</div>`
})
export class FlexibleComponent {
  // Using inject() with optional
  private logger = inject(LoggerService, { optional: true });

  doSomething() {
    // Check if logger is available
    this.logger?.log('Action performed');
  }
}

// Using constructor with @Optional
export class LegacyFlexibleComponent {
  constructor(@Optional() private logger?: LoggerService) {}

  doSomething() {
    this.logger?.log('Action performed');
  }
}
```

## Self and SkipSelf

Control dependency resolution:

```typescript theme={null}
import { Component, inject, Self, SkipSelf } from '@angular/core';
import { DataService } from './data.service';

@Component({
  selector: 'app-scoped',
  standalone: true,
  providers: [DataService],
  template: `<div>Scoped component</div>`
})
export class ScopedComponent {
  // Inject only from this component's injector
  private localService = inject(DataService, { self: true });
  
  // Skip this component's injector, use parent
  private parentService = inject(DataService, { skipSelf: true });
}
```

## Hierarchical Injection

Angular creates a hierarchy of injectors:

<Steps>
  <Step title="Platform Injector">
    Shared across all applications on the page
  </Step>

  <Step title="Root Injector">
    Application-wide services (providedIn: 'root')
  </Step>

  <Step title="Module Injectors">
    Created for lazy-loaded modules (legacy)
  </Step>

  <Step title="Component Injectors">
    Created when components have providers
  </Step>

  <Step title="Element Injectors">
    Created for directives with providers
  </Step>
</Steps>

```typescript theme={null}
import { Component, Injectable } from '@angular/core';

@Injectable()
class CounterService {
  count = 0;
  increment() { this.count++; }
}

@Component({
  selector: 'parent-component',
  standalone: true,
  providers: [CounterService], // Parent instance
  template: `
    <h2>Parent: {{ counter.count }}</h2>
    <button (click)="counter.increment()">Increment</button>
    <child-component />
  `
})
export class ParentComponent {
  counter = inject(CounterService);
}

@Component({
  selector: 'child-component',
  standalone: true,
  // No providers - inherits from parent
  template: `
    <h3>Child: {{ counter.count }}</h3>
    <button (click)="counter.increment()">Increment</button>
  `
})
export class ChildComponent {
  counter = inject(CounterService); // Same instance as parent
}
```

## Best Practices

1. **Use inject()** over constructor injection for modern applications
2. **Provide in root** for application-wide singletons
3. **Use component providers** for component-specific state
4. **Leverage injection tokens** for configuration and non-class dependencies
5. **Keep services focused** on single responsibilities
6. **Avoid circular dependencies** between services
7. **Use factory providers** for complex initialization logic

## Next Steps

<CardGroup cols={2}>
  <Card title="Services" href="/concepts/services">
    Learn to create and use services
  </Card>

  <Card title="Components" href="/concepts/components">
    Understand component architecture
  </Card>
</CardGroup>
