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

Introduction to Angular Dependency Injection

The Angular dependency injection is now the core part of the Angular. It allows us to inject dependencies into the Component, Directives, Pipes, or Services. In this tutorial, we will learn what is Angular Dependency Injection is and how to inject dependency into a Component, Directives, Pipes, or a Service by using an example

What is Dependency

We built an ProductService in the Angular Services tutorial. The AppComponent depends on the ProductService to provide the list of Products to display. You can view the code fromStackBlitz

In short, the AppComponent has a dependency on ProductService.

What is Angular Dependency Injection

Dependency Injection (DI) is a technique in which a class receives its dependencies from external sources rather than creating them itself.

Let us look at the ProductService, which we created in our Angular Services. tutorial You can refer to the code fromStackBlitz.

Our ProductService returns the hard-coded products when getProduct method invoked.

                              
product.service.ts

import {Product} from './Product'
 
export class ProductService{
 
    public  getProducts() {
 
        let products:Product[];
 
        products=[
            new Product(1,'Memory Card',500),
            new Product(1,'Pen Drive',750),
            new Product(1,'Power Bank',100)
        ]
 
        return products;               
    }
}
 
StackBlitz
                            
                        

Product Model

We instantiated the productService directly in our Component as shown below.

app.component.ts
                              

import { Component } from '@angular/core';
 
import { ProductService } from './product.service';
import { Product } from './product';
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
})
 
export class AppComponent
{
   products:Product[];
   productService;
 
   constructor(){
     this.productService=new ProductService();
   }
 
   getProducts() {
     
     this.products=this.productService.getProducts();
   }
 
}
 
StackBlitz
                            
                        

The ProductService Instance is local to the Component. The AppComponent is now tightly coupled to the ProductService, This tight coupling brings a lot of Issues.

The ProductService hardcoded in our AppComponent. What if we want to use BetterProductService. We need to change wherever the ProductService is used and rename it to BetterProductService.

What if ProductService depends on another Service. And then we decide to change the service to some other service. Again we need to search and replace the code manually

It is hard to test this Component as it is difficult to provide the Mock for the ProductService. For Instance, what if we wanted to substitute out the implementation of ProductService with MockProductService during testing.

Our Component Class has now tied one particular implementation of ProductService. It will make it difficult to reuse our components.

We would also like to make our ProductService singleton so that we can use it across our application.

How to solve all these problems. Move the creation of ProductService to the constructor the AppComponent class as shown below.

                              

export class AppComponent {    
   products:Product[];    
 
   constructor(private productService:ProductService) {    
 
   }    
 
   getProducts() {        
       this.products=this.productService.getProducts();    
   }
}
 
                            
                        

Our AppComponent does not create the instance of the ProductService. It just asks for it in its Constructor. The responsibility of Creating the ProductService falls on the creator of the AppComponent.

The above pattern is the Dependency Injection Pattern.

Benefits of Dependency Injection

loosely coupled

Our Component is now loosely coupled to the ProductService.

AppComponent does not know how to create the ProductService. Actually, it does not know anything about the ProductService. It just works with the ProductService passed on to it. You can pass ProductService,BetterProductService or MockProductService. The AppComponent does not care.

Easier to Test

AppComponent is now easier to Test. Our AppComponent is not dependent on a particular implementation of ProductService anymore. It will work with any implementation of ProductService that is passed on to it. You can just create a mockProductService Class and pass it while testing.

Reusing the Component

Reusing of the component is becomes easier. Our Component will now work with any ProductService as long as the interface is honored.

Dependency injection pattern made our AppComponent testable, maintainable, etc.

But does it solve all our Problem ?. No, we just moved the Problem out of Component to the Creator of the Component.

How do we create an instance of ProductService and pass it to the AppComponent? That is what Angular Dependency Injection does.

Angular Dependency Injection Framework

Angular Dependency Injection framework implements the Dependency Injection in Angular. It creates & maintains the Dependencies and injects them into the Components, Directives, or Services.

There are five main players in the Angular Dependency injection Framework.

Consumer

The Consumer is the class (Component, Directive, or Service) that needs the Dependency. In the above example, the AppComponent is the Consumer.

Dependency

The Service that we want to in our consumer. In the above example the ProductService is the Dependency

Injection Token (DI Token)

The Injection Token (DI Token) uniquely identifies a Dependency. We use DI Token when we register dependency

Provider

The Providers Maintain the list of Dependencies along with their Injection Token. It uses the Injection Token is to identify the Dependency.

Injector

Injector holds the providers and is responsible for resolving the dependencies and injecting the instance of the Dependency to the Consumer

The Injector uses Injection Token to search for Dependency in the providers. It then creates an instance of the dependency and injects it into the consumer

Using Dependency Injection

Registering the Dependency with the Injector

Angular Provides an instance of Injector & Provider to every component & directive in the application ( Consumers). It also creates an Injector instance at the module level and also at the root of the application. Basically, it creates a Tree of Injectors with parent-child relationship

The dependencies are registered with the Provider. This is done in the Providers metadata of the Injector.

                              

providers: [ProductService]
                            
                        

For Example, in the following code ProductService is registered with the Injector of the AppComponent

                              

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  providers: [ProductService]
})
export class AppComponent
{
 
                            
                        

We can also add the Services to Providers array of the @NgModule. Then they will be available for use in all the components & Services of the application. The ProductService in this case added to the Injector instance at the module level.

                              

@NgModule({
  declarations: [...],
  imports: [...],
  providers: [ProductService],
  bootstrap: []
})
                            
                        

Asking for Dependency in the Constructor

The Components, Directives & Services (Consumers) declare the dependencies that they need in their constructor.

                              

constructor(private productService:ProductService) { 
}
                            
                        

Injector reads the dependencies from the constructor of the Consumer. It then looks for that dependency in the provider. The Provider provides the instance and injector, then injects it into the consumer.

If the instance of the Dependency already exists, then it will reuse it. This will make the dependency singleton.

Angular Dependency Injection Example

We had created a simple ProductService in our last tutorial. Let us now update it to use Dependency Injection.

First, we need to register the dependencies with the provider. This is done in the providers metadata array of @Component decorator.

                              

providers: [ProductService]
                            
                        

Next, we need to tell angular that our component needs dependency injection. This is done by using the @Injectable() decorator.

@Injectable decorator is not needed if the class already has otherAngular decorators like @Component, @pipe or @directive etc. Because all these are a subtype of Injectible.

Since our AppComponent is already decorated with @Component, we do not need to decorate with the @Injectable

Next, our AppComponent needs to ask for the dependencies. We do that in the constructor of the Component.

                              

 
constructor(private productService:ProductService) { 
}
 
                            
                        

That’s it.

When AppComponent is instantiated it gets its own Injector instance. The Injector knows that AppComponent requires ProductService by looking at its constructor. It then looks at the Providers for a match and Provides an instance of ProductService to the AppComponent

The Complete AppComponent is as follows. You can refer to theStackblitz for the source code.

                              
 
import { Component } from '@angular/core';
 
import { ProductService } from './product.service';
import { Product } from './product';
 
@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  providers: [ProductService]
})
export class AppComponent
{
 
   products:Product[];
   
   constructor(private productService:ProductService){
   }
   
   getProducts() {
     this.products=this.productService.getProducts();
   }
  
}
                            
                        

Injecting Service into Another Service

We looked at how to inject ProductService to a component. Now let us look at how to inject service into another service.

Let us build loggerService, which logs every operation into a console window and inject it into our ProductService.

Logger Service

Create the logger.service.ts and add the following code

                              

import { Injectable } from '@angular/core';
 
@Injectable()
export class LoggerService {
  log(message:any) {
    console.log(message);
  }
}
 
                            
                        

The LoggerService has just one method log, which takes a message and writes it to the console.

We are also using @Injectible metadata to decorate our logger class. Technically, we do not have to do that as the logger service does not have any external dependencies.

Product Service

Now we want to inject this into our ProductService class

The ProductService needs loggerService to be injected. Hence the class requires @Injectible metadata

                              

@Injectable()
export class ProductService{}
 
                            
                        

Next, In the constructor of the ProductService ask for the loggerService.

                              

constructor(private loggerService: LoggerService) {
    this.loggerService.log("Product Service Constructed");
}
 
                            
                        

And update the GetProducts method to use the Logger Service.

                              

 public  getProducts() {
 
        this.loggerService.log("getProducts called");
        let products:Product[];
 
        products=[
            new Product(1,'Memory Card',500),
            new Product(1,'Pen Drive',750),
            new Product(1,'Power Bank',100)
        ]
 
        this.loggerService.log(products);
        return products;               
    }
 
                            
                        

Finally, we need to register LoggerService with the Providers metadata.

Open the AppComponent update the providers array to include LoggerService

                              

providers: [ProductService,LoggerService]
                            
                        

That’s it. As you click on the Get Products button, you will see the Console window updated with the Log messages

Providing Dependency from Angular Module

In the above example, we registered the dependencies in the Providers array of the component class. The dependencies are only available to the component where we register them and to its child components.

To Make the dependencies available to the entire application, we need to register it in the root module.

Remove the providers: [ProductService,LoggerService], from the AppComponent and move it to the AppModule as shown below

                              

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { HttpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';
 
import { AppComponent } from './app.component';
 
import { ProductService } from './product.service';
import { LoggerService } from './logger.service';
 
@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpModule,
    FormsModule
  ],
  providers: [ProductService,LoggerService],
  bootstrap: [AppComponent]
})
export class AppModule { }
 
Stackblitz
                            
                        

Providing the service in the root module will create a single, shared instance of service and injects into any class that asks for it.

The above code works because Angular creates the Tree of Injectors with parent-child relationship similar to the Component Tree. We will cover it in the next tutorial.

ProvidedIn

Instead of adding ProductService to providers of the AppModule, you can also add it in the providedIn metadata with the value root.

In fact, using the ProvidedIn is the preferred way to provide a service in a module

                              

@Injectable({
  providedIn:'root'
})
export class ProductService {
 
                            
                        
                              
 
@Injectable({
  providedIn:'root'
})
export class LoggerService {
 
                            
                        

Service Scope

The services that we provide at the root module are app-scoped, which means that we can access them from every component/service within the app.

Any service provided in the other Modules (Other than the Lazy Loaded Module) is also available for the entire application.

The services that are provided in a Lazy Loaded Module are module scoped and available only in the Lazy loaded module.

The services provided at the Component level are available only to the Component & and to the child components.