Angular Tutorial 0/42 lessons ~6 min read Lesson 26

    Angular Advanced DI

    Learn Angular Advanced Dependency Injection, including injectors, hierarchical DI, providedIn, inject(), provider types, Injection Tokens, multi providers, lookup decorators (@Self, @SkipSelf, @Host, @Optional), route-level and feature DI, plugin architecture, enterprise best practices, and interview questions.

    Course progress0%
    Focus
    39 guided sections
    Practice signal
    Examples included
    Career prep
    Interview Q&A included

    Learning Objectives

    By the end of this lesson, you will understand:

    • What Dependency Injection (DI) is.
    • Why Angular uses DI.
    • How Angular's Injector works internally.
    • The Dependency Injection lifecycle.
    • Hierarchical Dependency Injection.
    • Root Injector.
    • Platform Injector.
    • Environment Injector.
    • Component Injector.
    • Route-level Injectors.
    • Tree-Shakable Providers.
    • The inject() API.
    • providedIn options (root, platform, any).
    • Class Providers.
    • Value Providers.
    • Factory Providers.
    • Existing Providers.
    • Injection Tokens.
    • Multi Providers.
    • Optional Injection.
    • @Self(), @SkipSelf(), @Host(), @Optional().
    • Feature-level DI architecture.
    • Plugin-based DI.
    • Enterprise DI best practices.
    • Common mistakes.
    • Advanced interview questions.

    Introduction

    Imagine TechLearningPro has hundreds of components.

    text
    Login Component
    Dashboard
    Course Component
    Quiz Component
    Certificate Component
    AI Tutor
    Admin Panel

    Every component needs services like:

    text
    Authentication
    Course Service
    Logger
    HttpClient
    Analytics
    Notification
    Configuration

    Should every component create these services using:

    typescript
    new AuthService()

    No.

    Angular automatically creates and manages these objects.

    This is called Dependency Injection (DI).

    What is Dependency Injection?

    Dependency Injection is a design pattern where Angular creates required objects (dependencies) and provides them to components or services.

    Instead of:

    typescript
    const service = new CourseService();

    Angular does:

    typescript
    constructor(
    private courseService: CourseService
    ){}

    Angular automatically injects the service.

    Why Dependency Injection?

    Without DI:

    text
    Component
    new Service()
    Hard Coupling

    Problems:

    • Difficult to test
    • Difficult to replace
    • Difficult to maintain

    With DI:

    text
    Component
    Angular Injector
    Service

    The component depends only on the contract, not object creation.

    Real-Time Example

    TechLearningPro

    text
    Course Component
    CourseService
    HttpClient
    Backend API

    The component never creates CourseService.

    Angular injects it automatically.

    Angular DI Architecture

    text
    Application Starts
    Create Root Injector
    Register Providers
    Component Requests Service
    Injector Creates Service
    Component Uses Service

    What is an Injector?

    An Injector is Angular's object factory.

    Responsibilities:

    • Create services.
    • Store services.
    • Reuse services.
    • Manage service lifetime.

    Architecture

    text
    Component
    Injector
    Create Object
    Return Service

    Service Lifecycle

    Suppose:

    typescript
    @Injectable()
    export class AuthService {}

    Application starts.

    text
    Root Injector
    AuthService
    Singleton
    Shared Everywhere

    Every component receives the same instance.

    Root Injector

    Most services use:

    typescript
    @Injectable({
    providedIn:'root'
    })

    Architecture

    text
    Application
    Root Injector
    AuthService
    Every Component

    Only one instance exists.

    Tree-Shakable Providers

    Example:

    typescript
    @Injectable({
    providedIn:'root'
    })

    If the service is never used:

    text
    Angular Build
    Unused Service
    Removed

    Smaller bundles.

    Platform Injector

    Some services belong to the Angular platform itself.

    Architecture

    text
    Browser
    Platform Injector
    Applications

    Rarely used directly.

    Environment Injector

    Modern Angular introduces the Environment Injector.

    Architecture

    text
    Application
    Environment Injector
    Router
    Feature
    Component

    This supports standalone applications and route-level providers.

    Component Injector

    Services can exist only inside one component.

    Example:

    typescript
    @Component({
    providers:[
    CourseStore
    ]
    })

    Architecture

    text
    Course Component
    CourseStore
    Only This Component

    Destroy the component.

    The service also disappears.

    Route-Level Injector

    Modern Angular supports:

    typescript
    {
    path:'courses',
    providers:[
    CourseStore
    ]
    }

    Architecture

    text
    Route
    Injector
    CourseStore
    All Child Components

    Excellent for feature isolation.

    Injector Hierarchy

    Angular searches upward.

    text
    Component Injector
    Route Injector
    Root Injector
    Platform Injector

    If not found:

    Angular continues upward.

    How Angular Resolves Dependencies

    Suppose:

    typescript
    constructor(
    private logger:
    LoggerService
    ){}

    Angular searches:

    text
    Component?
    Route?
    Root?
    Platform?
    Error

    inject() API

    Modern Angular prefers:

    typescript
    logger = inject(
    LoggerService
    );

    Instead of constructor injection.

    Advantages:

    • Cleaner code
    • Better readability
    • Works inside functions

    providedIn Options

    Root

    typescript
    providedIn:'root'

    Singleton.

    Platform

    typescript
    providedIn:'platform'

    Shared across applications on the same page.

    Any

    typescript
    providedIn:'any'

    Creates separate instances for different injectors when appropriate, often useful with lazy-loaded boundaries.

    Class Provider

    typescript
    providers:[
    LoggerService
    ]

    Equivalent:

    typescript
    {
    provide:LoggerService,
    useClass:LoggerService
    }

    Value Provider

    Useful for configuration.

    typescript
    {
    provide:API_URL,
    useValue:
    'https://api.techlearningpro.com'
    }

    Architecture

    text
    Injector
    API_URL
    String

    Factory Provider

    Sometimes service creation is dynamic.

    typescript
    {
    provide:Logger,
    useFactory:loggerFactory
    }

    Architecture

    text
    Injector
    Factory
    Logger

    Existing Provider

    Reuse another service.

    typescript
    {
    provide:Logger,
    useExisting:ConsoleLogger
    }

    Both tokens reference the same instance.

    Injection Tokens

    Primitive values require tokens.

    typescript
    export const API_URL =
    new InjectionToken<string>(
    'API_URL'
    );

    Inject:

    typescript
    inject(API_URL);

    Architecture

    text
    Token
    Injector
    Value

    Multi Providers

    Useful for plugins.

    Example:

    typescript
    {
    provide:HTTP_INTERCEPTORS,
    multi:true,
    useClass:AuthInterceptor
    }

    Another:

    typescript
    {
    provide:HTTP_INTERCEPTORS,
    multi:true,
    useClass:LoggingInterceptor
    }

    Architecture

    text
    Injector
    HTTP_INTERCEPTORS
    Interceptor[]
    Many Objects

    Optional Injection

    Sometimes dependency may not exist.

    typescript
    inject(
    LoggerService,
    {
    optional:true
    }
    );

    If missing:

    text
    null

    instead of an error.

    @Self()

    Search only current injector.

    text
    Current Component
    Service?
    Yes
    Stop

    @SkipSelf()

    Ignore current injector.

    Start from parent.

    Architecture

    text
    Skip Current
    Parent
    Root

    @Host()

    Limit lookup to the current host boundary.

    Useful in advanced component composition scenarios.

    @Optional()

    Dependency may not exist.

    Application continues.

    Real-Time Example

    TechLearningPro

    text
    Root
    Authentication
    Logger
    Analytics
    ---------------------
    Course Route
    CourseStore
    Course Components

    Authentication is global.

    CourseStore exists only for Course pages.

    Feature-Level Architecture

    text
    Application
    ├── Authentication
    ├── Dashboard
    ├── Courses
    ├── Practice
    └── Admin

    Each feature owns:

    text
    Services
    Signals
    Stores
    Injectors

    Excellent scalability.

    Plugin Architecture

    text
    Plugin
    Injection Token
    Plugin Loader
    Dynamic Service

    Perfect for enterprise platforms.

    TechLearningPro Architecture

    text
    Root Injector
    ├── AuthService
    ├── Analytics
    ├── Logger
    ├── Theme
    Course Route
    ├── CourseStore
    ├── QuizStore
    └── ProgressStore
    Course Components

    Enterprise Best Practices

    Prefer:

    • inject() over constructor injection where it improves readability.
    • Route-level providers.
    • Feature-level services.
    • Injection Tokens for configuration.
    • Multi Providers for extensibility.
    • Tree-shakable providers.

    Avoid:

    • Giant global services.
    • Everything inside the Root Injector.
    • Creating services using new.
    • Tight coupling.

    Common Mistakes

    Creating Services Manually

    Avoid:

    typescript
    const auth =
    new AuthService();

    Always let Angular create services.

    Too Many Root Services

    Not everything belongs in the Root Injector.

    Feature-specific state should remain inside feature injectors.

    Configuration Hardcoded

    Use:

    text
    InjectionToken
    Configuration

    Instead of constants scattered across the application.

    Massive Services

    Split:

    text
    CourseService
    QuizService
    CertificateService
    ProgressService

    Instead of one 5,000-line service.

    Enterprise DI Architecture

    text
    Browser
    Platform Injector
    Root Injector
    Route Injector
    Component Injector
    Component

    Each level owns only what it needs.

    Advanced interview questions

    Interview Prep

    Practice concise answers, then expand each card for the explanation.

    10 questions
    1BeginnerQuestionWhat is Dependency Injection?+

    Answer

    Dependency Injection is a design pattern where Angular creates and provides object dependencies instead of components creating them manually.
    2BeginnerQuestionWhat is an Injector?+

    Answer

    An Injector is Angular's container responsible for creating, storing, and providing service instances.
    3BeginnerQuestionWhat is `providedIn:'root'`?+

    Answer

    It registers the service with the Root Injector, creating a singleton instance shared across the application.
    4IntermediateQuestionWhy use `inject()`?+

    Answer

    inject() provides a concise way to obtain dependencies without constructor injection and is especially useful in standalone APIs, guards, interceptors, and factory functions.
    5IntermediateQuestionWhat are Injection Tokens?+

    Answer

    Injection Tokens allow Angular to inject values or interfaces that don't have a runtime class representation, such as configuration objects or primitive values.
    6IntermediateQuestionWhat are Multi Providers?+

    Answer

    They allow multiple implementations to be registered under the same token, commonly used for HTTP interceptors and plugin systems.
    7IntermediateQuestionDifference between Root Injector and Component Injector?+

    Answer

    The Root Injector provides application-wide singletons that are long-lived. A Component Injector exists only for that component subtree and is destroyed with the component.
    8AdvancedQuestionWhat is the Injector Hierarchy?+

    Answer

    Angular searches for dependencies from the nearest injector upward. Component → Route → Root → Platform.
    9AdvancedQuestionWhat is Tree-Shakable DI?+

    Answer

    Services registered with providedIn can be removed from production bundles if they are never used, reducing application size.
    10AdvancedQuestionWhat is the recommended enterprise architecture?+

    Answer

    Root → Authentication/Analytics → Feature Routes → Feature Stores → Signals → Components. This architecture keeps global services global and feature-specific services isolated.

    Summary

    Dependency Injection is one of Angular's core architectural strengths.

    text
    Application Starts
    Platform Injector
    Root Injector
    Route Injector
    Component Injector
    Service Resolution
    Components

    For TechLearningPro, an ideal DI architecture is:

    text
    Root Injector
    ├── AuthService
    ├── HttpClient
    ├── AnalyticsService
    ├── LoggerService
    ├── Angular Course Route
    │ ├── CourseStore
    │ ├── ProgressStore
    │ └── QuizStore
    ├── Java Course Route
    │ ├── CourseStore
    │ └── PracticeStore
    └── Admin Route
    ├── UserManagementService
    └── ReportStore

    The core principle: Let Angular create and manage your dependencies. Keep global services in the Root Injector, feature-specific state in route or component injectors, and use Injection Tokens and hierarchical DI to build scalable, testable, enterprise-grade Angular applications.

    Next Lesson

    Angular HTTP Interceptors — You'll learn:

    • Request lifecycle
    • Functional interceptors (HttpInterceptorFn)
    • withInterceptors()
    • JWT authentication
    • Token refresh flow
    • Request/response transformation
    • Global error handling
    • Retry strategies
    • Caching
    • Request deduplication
    • Correlation IDs
    • Logging and monitoring
    • Loading indicators
    • Enterprise interceptor architecture
    • Advanced interview questions
    Ready to mark this lesson complete?Track your journey across the entire course.