ANGULAR
Complete Angular Tutorial For Beginners Introduction to Angular | What is Angular? Architecture Overview & Concepts of Angular How to Install Angular How to Create a new project in Angular Bootstrapping in Angular: How It Works Internally Angular Components Overview & Examples Data Binding in Angular Interpolation in Angular Property Binding in Angular Event Binding in Angular ngModel & Two way Data binding in Angular NgModelChange & Change Event in Angular Child/Nested Components in Angular angular directives angular ngFor directive ngSwitch, ngSwitchcase, ngSwitchDefa ult Angular Example How to use ngIf, else, then in Angular By example NgClass Example Conditionally apply class Angular ngStyle Directive Angular Trackby to improve ngFor Performance How to Create & Use Custom Directive In Angular Working with Angular Pipes How to Create Custom Pipe in Angular Formatting Dates with Angular Date Pipe Using Angular Async Pipe with ngIf & ngFor angular keyValue pipe Using Angular Pipes in Components or Services Angular Component Communication & Sharing Data Angular Pass data to child component Angular Pass data from Child to parent component Component Life Cycle Hooks in Angular Angular ngOnInit And ngOnDestroy Life Cycle hook Angular ngOnChanges life Cycle Hook Angular ngDoCheck Life Cycle Hook Angular Forms Tutorial: Fundamentals & Concep t s Angular Template-driven forms example How to set value in template-driven forms in Angular Angular Reactive Forms Example Using Angular FormBuilder to build Forms SetValue & PatchValue in Angular StatusChanges in Angular Forms ValueChanges in Angular Forms FormControl in Angular FormGroup in Angular Angular FormArray Example Nested FormArray Example Add Form Fields Dynamically SetValue & PatchValue in FormArray Angular Select Options Example in Angular Introduction to Angular Services Introduction to Angular Dependency Injection Angular Injector, @Injectable & @Inject Angular Providers: useClass, useValue, useFactory & useExisting Injection Token in Angular How Dependency Injection & Resolution Works in Angular Angular Singleton Service ProvidedIn root, any & platform in Angular @Self, @SkipSelf & @Optional Decorators Angular '@Host Decorator in Angular ViewProviders in Angular Angular Reactive Forms Validation Custom Validator in Angular Reactive Form Custom Validator with Parameters in Angular Inject Service Into Validator in Angular template_driven_form_validation_in_angular Custom Validator in Template Driven Forms in Angular Angular Async Validator Example Cross Field or Multi Field Validation Angular How to add Validators Dynamically using SetValidators in Angular Angular HttpClient Tutorial & Example Angular HTTP GET Example using httpclient Angular HTTP POST Example URL Parameters, Query Parameters, httpparams in Angular HttpClient Angular HTTPHeaders Example Understanding HTTP Interceptors in Angular Angular Routing Tutorial with Example Location Strategy in Angular Angular Route Params Angular : Child Routes / Nested Route Query Parameters in Angular Angular Pass Data to Route: Dynamic/Static RouterLink, Navigate & NavigateByUrl to Navigate Routes RouterLinkActive in Angular Angular Router Events ActivatedRoute in Angular Angular Guards Tutorial Angular CanActivate Guard Example Angular CanActivateChild Example Angular CanDeactivate Guard Angular Resolve Guard Introduction to Angular Modules or ngModule Angular Routing between modules Angular Folder Structure Best Practices Guide to Lazy loading in Angular Angular Preloading Strategy Angular CanLoad Guard Example Ng-Content & Content Projection in Angular Angular @input, @output & EventEmitter Template Reference Variable in Angular ng-container in Angular How to use ng-template & TemplateRef in Angular How to Use ngTemplateOutlet in Angular '@Hostbinding and @Hostlistener_in_Angular Understanding ViewChild, ViewChildren &erylist in Angular ElementRef in Angular Renderer2 Example: Manipulating DOM in Angular ContentChild and ContentChildren in Angular AfterViewInit, AfterViewChecked, AfterContentInit & AfterContentChecked in Angular Angular Decorators Observable in Angular using RxJs Create observable from a string, array & object in angular Create Observable from Event using FromEvent in Angular Using Angular observable pipe with example Angular Map Operator: Usage and Examples Filter Operator in Angular Observable Tap operator in Angular observable Using SwitchMap in Angular Using MergeMap in Angular Using concatMap in Angular Using ExhaustMap in Angular Take, TakeUntil, TakeWhile & TakeLast in Angular Observable First, Last & Single Operator in Angular Observable Skip, SkipUntil, SkipWhile & SkipLast Operators in Angular The Scan & Reduce operators in Angular DebounceTime & Debounce in Angular Delay & DelayWhen in Angular Using ThrowError in Angular Observable Using Catcherror Operator in Angular Observable ReTryWhen inReTry, ReTryWhen in Angular Observable Unsubscribing from an Observable in Angular Subjects in Angular ReplaySubject, BehaviorSubject & AsyncSubject in Angular Angular Observable Subject Example Sharing Data Between Components Angular Global CSS styles View Encapsulation in Angular Style binding in Angular Class Binding in Angular Angular Component Styles How to Install & Use Angular FontAwesome How to Add Bootstrap to Angular Angular Location Service: go/back/forward Angular How to use APP_INITIALIZER Angular Runtime Configuration Angular Environment Variables Error Handling in Angular Applications Angular HTTP Error Handling Angular CLI tutorial ng new in Angular CLI How to update Angular to latest version Migrate to Standalone Components in Angular Create Multiple Angular Apps in One Project Set Page Title Using Title Service Angular Example Dynamic Page Title based on Route in Angular Meta service in Angular. Add/Update Meta Tags Example Dynamic Meta Tags in Angular Angular Canonical URL Lazy Load Images in Angular Server Side Rendering Using Angular Universal The requested URL was not found on this server error in Angular Angular Examples & Sample Projects Best Resources to Learn Angular Best Angular Books in 2020

How Dependency Injection & Resolution Works in Angular

In this tutorial, we will look at how Angular dependency injection works. The Angular creates a hierarchical dependency injection system. It creates a hierarchical tree of Injectors. Each Injector gets their own copy of Angular Providers. Together these two form the core of the Angular dependency injection framework. We will learn how Angular creates the injector tree.How injector resolves the dependency.

Injector

The Angular creates an Injector instance for every Component , Directive, etc it loads. It also creates an injector instance for theRoot Module and for every lazy loaded module. But eagerly loaded modules do not get their own injector but share the injector of the Root Module.

Injector Tree

Angular Creates not one but two injector trees. Module Injector tree & Element Injector tree.

Module Injector tree is for Modules (@NgModule). For Root Module & for every Lazy Loaded Module.

Element Injector tree is for DOM Elements like Components & Directives.

Module Injector Tree

Angular creates the ModuleInjector for the services to be provided at Module Levels.

We register the Module level services in two ways

  • Using The Providers Metadata of the @NgModule, ()
  • Using the@Injectable,() Decorator with providedIn : root in the service itself
  • Angular Creates the Module Injector tree when the Application starts.

    At the top of the Module Injector tree , Angular creates an instance of Null Injector. The Null Injector always throws an error unless we decorate the dependency with the Optional decorator.

    Under Null Injector Angular creates an instance of PlatformInjector. Platform Injector usually includes built-in providers like DomSanitize etc.

    image

    Under the Platform Injector, Angular creates the Injector for the Root Module. It is configured with the providers from the following locations.

  • Providers metadata of @NgModule of Root Module.
  • Providers metadata of @NgModule of all the imported Modules (i.e. all eagerly loaded modules).
  • All the services which have providedIn metadata with value root or any in their @Injectable() decorator. It includes services from both eagerly loaded & Lazy Loaded Modules.
  • Under Root Module Injector, Angular creates an Injector instance for every Lazy loaded Module. Angular creates them only when it loads them. They are configured with the providers from the following locations.

  • Providers metadata of @NgModule of the Module being Lazy loaded
  • All the services which have providedIn metadata with value any in their @Injectable() decorator
  • Element Injector Tree

    Angular creates the Element Injector tree for the services to be provided at the element level like Components & Directives.

    Angular creates the Element Injector tree when the application starts.

    The Injector instance of the Root Component becomes the root Injector for the Element Injector tree. It gets the Providers from the provider’s property of the Root Component.

    The Root Component acts as a parent to every element ( i.e. Component or Directives) we create. Each of those elements can contain child elements creating a tree of elements. The Angular creates an Injector for each of these elements creating a tree of Injectors.

    Each Injector gets the list of Providers from the @Directive() or @Component(). If the Providers array is empty, then Angular creates an empty Injector.

    The Angular will destroy the Injector when Angular destroys the element.

    image

    Dependency Resolution

    Angular resolves the dependency in two phases

  • First, resolve it using the Element Injector and its parents
  • If not found in the Element Injector, then resolve it against the Module Injector and its parents.
  • The components ask for the dependencies in the constructor using the token.

    The search starts at the Injector associated with the component in the Element Injector tree. It uses the token to search for dependency in its Providers array. If it finds the provider, Injector checks to see if the instance of the service already exists. If exists then it injects it into the component else it creates a new instance of it. Then it injects it into the component.

    Injector passes the request to the parent Injector in the Element Injector Hierarchy if it fails to find the provider. If the provider is found, the request returns the instance of the Provider. If not found then the request continues until the request reaches the topmost injector in the Element Injector tree.

    The topmost Injector in the Element Injector tree belongs to the root component. If the dependency is not found, it does not throw the error but returns back.

    Now, the search shifts to Module Injector Tree

    Search starts from the Injector associated with the module to which the element belongs. For the Root Modules & Eagerly loaded Module the search starts from the Root Module Injector. For components from the lazy loaded modules, the resolutions start from the Module Injector associated with Lazy Loaded Module.

    The request continues until the request reaches the topmost injector in the Module Injector tree i.e. Null Injector. The Null Injector does not contain any providers. Its job is to throw No provider for Service error. But if we decorate the dependency with @Optional decorator, then it will return null instead of throwing an error.

    Dependency Resolution in Picture

    The following image shows how Angular Resolves the Dependency for Component in a Root Module.

    The component (GrChildComponentA) asking for dependency is in the RootModule. The search starts in the Element Injector hierarchy starting with the Injector associated with the GrChildComponentA. The search moves up the Injector tree to reach the Root Injector, which belongs to the RootComponent. If the service not found, the search shifts to Module Injector Hierarchy starting from Root Module (because GrChildComponentA belongs to Root Module).

    image

    The following image shows how Angular Resolves the Dependency for Component in a Lazy Loaded Module

    The component (LazyBChildComponent) asking for dependency is in the LazyModuleB. As you can see, once the Injectors from the Element Injector tree fail to provide the service, the request shifts to Module Injector Hierarchy. The starting point for the search is the Module to which LazyBChildComponent belongs i.e. LazyModuleB.

    image image

    Notes on Dependency Resoultion

    Module Injector Tree is not a parent of Element Injector Tree. Each Element can have the same parent Element Injector Tree, but a different parent in Module Injector Tree

    No Injectors from Eager Modules. They share it with the Root Module.

    Separate Injector for Lazy Loaded Modules in Module Ejector Tree

    If two Eager Modules, provide the service for the same token, the module, which appears last in the imports array wins. For Example in the following imports, providers of Eager2Module overwrites the providers of the Eager1Module for the same token

                                  
    
    imports: [BrowserModule, FormsModule, Eager1Module, Eager2Module],
                                
                            

    If Eager Module & Root Module provide the service for the same token, then the Root module wins

    Any service with providedIn value of root in the lazy loaded module, become part of the Root Module Injector.

    To restrict service to the lazy loaded module, remove it from the providedIn and add it in the provider’s array of the Module.

    The Services are singletons within the scope of an injector. When the injector gets a request for a particular service for the first time, it creates a new instance of the service. For all the subsequent requests, it will return the already created instance.

    The Injectors are destroyed when Angular removes the associated Module or element.

    Where you configure your services, will decide the service scope, service lifetime & bundle size.

    You can use Resolution Modifiers to modify the behavior of injectors. Refer to the @Self, @SkipSelf & @Optional Decorators & @Host Decorator in Angular

    Example of hierarchical dependency injection

    You can download the sample application from Stackblitz

    The App has a RootModule,EagerModule & LazyModule.

    All the modules have one service each. Each generates a random number. We affix the number with the name of the service so that you will know the service has generated it.

    The code from the AppService. Other services are almost identical

    app.service.ts
                                  
    
    import { Injectable } from '@angular/core';
     
    @Injectable,()
    export class AppService {
      sharedValue: string;
     
      constructor() {
        console.log('Shared Service initialised');
        this.sharedValue = 'App:' + Math.round(Math.random() * 100);
        console.log(this.sharedValue);
      }
     
      public getSharedValue() {
        return this.sharedValue;
      }
    }
     
                                
                            

    All Components inject all services and display the result. We use the @Optional,() decorator. This will ensure that the Injector returns null instead of an error if the dependency not found.

                                  
    
    import { Component, Optional } from '@angular/core';
    import { AppService } from './app.service';
    import { EagerService } from './eager/eager.service';
    import { LazyService } from './lazy/lazy.service';
     
    @Component({
      selector: 'parent1-component',
      template: `
        <div class="box">
          <strong>Parent1</strong>
          {{ appValue }}
          {{ eagerValue }}
          {{ lazyValue }}
     
          <child1-component></child1-component>
          <child2-component></child2-component>
     
        </div>
      `,
      providers: []
    })
    export class Parent1Component {
      appValue;
      eagerValue;
      lazyValue;
     
      constructor(
        @Optional,() private appService: AppService,
        @Optional,() private eagerService: EagerService,
        @Optional,() private lazyService: LazyService
      ) {
     
        this.appValue = appService?.getSharedValue();
        this.eagerValue = eagerService?.getSharedValue();
        this.lazyValue = lazyService?.getSharedValue();
      }
    }
                                
                            

    Now, let us play around and see the effect of providing the services at various places.

    Provide Services in the respective Modules

    Use the Providers array to add the AppService, EagerService & LazyService in their respective NgModules(Stackblitz).

    image
  • AppService & EagerService returns the same value everywhere because they are available in the RootModule Injector.
  • LazyService is available only in the LazyModule Injector. Hence available only in the LazyComponent.
  • You can try out the following

  • Register EagerService in AppModule instead of EagerModule
  • Add providedIn: 'root' to both EagerService & AppService.
  • Both will result in a similar result

    Using ProvidedIn in LazyService

    1. Add the providedIn: 'root' for the LazyService. Now LazyService is added to Root Module Injector.
    2. Remove LazyService from the Provider’s Array of LazyModule
                                  
    
    @Injectable({ providedIn: 'root' })
    export class LazyService {
                                
                            

    Since the LazyService is now available Root Module Injector, it will be available across the application as a singleton (Code).

    image

    You can try out the following

  • Keep the providedIn: 'root' for the LazyService.
  • Add LazyService to the Providers array of the LazyModule.
  • Now LazyService available at two Injectors. In RootModule Injector & in LazyModule Injector. The LazyComponent will use the service from the LazyModule Injector, while the rest of the App uses it from the RootModule Injector. Hence you get two different values

    LazyService in AppComponent

    1. Keep the providedIn: 'root' for the LazyService.
    2. Add LazyService to the Providers array of the LazyModule.
    3. Add LazyService to the Providers array of the AppComponent.

    Now LazyService available at three Injectors (code). RootModule Injector, LazyModule Injector & AppComponent Injector. The AppComponent Injector is the root of the Element Injector Tree. All Components are children of the AppComponent. Hence all of them get the same value.

    Services in a Component

    Register the AppService in the Providers array of Parent1Component.

    As you can see from the image below, the Parent1Component & all its child components gets their copy of AppService from the Parent1Component while rest of the App gets it from AppModule

    image