How to use Interceptor in Angular

Interceptors are used to intercepts HTTP requests and responses from the application. You can handle them or transform them before passing it on. For example, you can use an interceptor to add authorization token before passing the HTTP request or cache the HTTP response. Some of the usages of interceptors are as follows,

  • Caching of the response
  • Adding request headers such as authorization or any custom header for all outgoing requests.
  • Handling HTTP response error
  • Manipulating the URL
  • Faking the API
  • Authentication for every ongoing request etc.

To implement an interceptor, create a service that implements the HttpInterceptor interface.  The HttpInterceptor interface has one method intercept, which returns observable of HttpEvent and takes two inputs of types HttpRequest and HttpHandler.

abc

You can create an interceptor service as shown below,



import { HttpInterceptor, HttpRequest, HttpHandler, HttpEvent } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

@Injectable()
export class GlobalInterceptor implements HttpInterceptor{

    intercept(request :HttpRequest<any>,next:HttpHandler):Observable<HttpEvent<any>>{

        console.log(request.url);
        console.log(request.headers);
        console.log(request.body);
        return next.handle(request);
       // return null; 
    }
}


The above interceptor is simply printing request URL, headers, and body before passing the request object to the next method such that it can send it to the server.

After creating the interceptor service, you need to provide it to the application root module level.



@NgModule({
  declarations: [
    AppComponent,
    ProductsComponent
  ],
  imports: [
    BrowserModule,
    AppRoutingModule,
    HttpClientModule
  ],
  providers: [{
    provide:ErrorHandler,useClass:GlobalErrorHandler},
   {provide:HTTP_INTERCEPTORS, useClass: GlobalInterceptor,multi:true}],
  bootstrap: [AppComponent]
})


 

Some important usage scenarios keep in mind that,

  • Import HttpClientModule only in the AppModule means root module
  • Add interceptors in the provide array of the AppModule
  • In case, if you import HttpClientModule in features module, then each module creates a copy of HttpClientModule, which overwrites the interceptor provided the AppModule.
  • You can provide more than one interceptor in the application. However, Angular apply them in the order they are provided.

Adding Headers

There are many usages of an interceptor, for example, if you want to set the header for every HTTP request, amend the request body, or set authorization header.  To set the header, first, clone the request object and set the header property.  You can also set the Content-Type and Accept header as shown below,



  // setting the header before sending the request
       const r = request.clone(
            {
            url:request.url.replace('http://','https://'),
            headers: request.headers.set('Content-Type', 'application/json')
            .set('Accept', 'application/json')
           }
        );

        return next.handle(r);


The above interceptor also replaces all request URLs from HTTP to HTTPS.  You can also set any new header means which are not standard HTTP header using the setHeader method,



 const r = request.clone(
            {
           // url:request.url.replace('http://','https://'),
            headers: request.headers.set('Content-Type', 'application/json')
            .set('Accept', 'application/json'),
            setHeaders:{'geek97':'ngIndia'}

           }
        );

        return next.handle(r);

 


Caching

The best way, you can use Interceptors request caching.  To cache requests, create an Angular service in which you register outgoing HTTP requests for caching.



import { Injectable } from "@angular/core";
import { HttpRequest, HttpResponse } from '@angular/common/http';

const maxAge = 20000;
@Injectable()
export class CacheRegistrationService {

    cache = new Map();
    get(req: HttpRequest<any>): HttpResponse<any> | undefined {
        const url = req.urlWithParams;
        const cached = this.cache.get(url);

        if (!cached) {
          return undefined;
        }

        const isExpired = cached.lastRead < (Date.now() - maxAge);
        const expired = isExpired ? 'expired ' : '';
        return cached.response;
      }

      put(req: HttpRequest<any>, response: HttpResponse<any>): void {
        const url = req.url;
        const entry = { url, response, lastRead: Date.now() };
        this.cache.set(url, entry);

        const expired = Date.now() - maxAge;
        this.cache.forEach(expiredEntry => {
          if (expiredEntry.lastRead < expired) {
            this.cache.delete(expiredEntry.url);
          }
        });
      }
}

 


 

You can have your own logic to register a request for the caching. However, I am just using a JavaScript Map() object to save outgoing requests for the caching.

I have written another post detailing about Maps in JavaScript here

Next, provide CacheRegisterationService at the AppModule level.



providers: [CacheRegistrationService, {
    provide: ErrorHandler, useClass: GlobalErrorHandler
  },
    { provide: HTTP_INTERCEPTORS, useClass: GlobalInterceptor, multi: true }],
  bootstrap: [AppComponent]


Now you can modify interceptor for caching as shown below,


@Injectable()
export class GlobalInterceptor implements HttpInterceptor {

  constructor(private cacheRegistrationService: CacheRegistrationService) {
    }
    intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {

       const cachedResponse = this.cacheRegistrationService.get(request);
       return cachedResponse ? of(cachedResponse) : this.sendRequest(request, next, this.cacheRegistrationService);

      // return this.sendRequest(request,next,this.cacheRegistrationService);

    }
    sendRequest(
        request: HttpRequest<any>,
        next: HttpHandler,
        cache: CacheRegistrationService): Observable<HttpEvent<any>> {

    // cloning the request to modify the hedaer 
       const r = request.clone(
            {
                // url:request.url.replace('http://','https://'),
                headers: request.headers.set('Content-Type', 'application/json')
                    .set('Accept', 'application/json'),
                setHeaders: { 'geek97': 'ngIndia' }

            }
        );

        // Making the request and caching 

        return next.handle(r).pipe(
            tap(event => {
                if (event instanceof HttpResponse) {
                    cache.put(r, event);
                }
            })
        );
    }
}


We are just checking whether requests are cached or not before making request. In the network tab, you can check that only one request is made for multiple GET operations on the same API URL.

Handling HTTP error

You can also use interceptors for handling HTTP communication errors.  You can capture HTTP response error 401 and before that try request two times as shown below,


return next.handle(r).pipe(

            retry(2),
            catchError((error :HttpErrorResponse)=>{
                if(error.status ){
                    // log the eroor. pass it to global error handler
                    alert('error 401')
                }
                return throwError(error);
            })
        );


 

These are the few scenarios in which you can use the interceptor. I hope you like this post. For online or onsite Angular training reach me at debugmode@outlook.com .

When to use the subscribe method or async pipe in Angular?

Let us start with depicting the usage of both ways of data retrieval with a high-level diagram:

dhananjay kumar

Commonly, we work with observable data in a component class. One such classic example is CRUD operations on a REST API. For this, mostly we use Angular’s HttpClient class’s methods to perform various HTTP request operations, which returns HTTP responses as an observable.

This blog post discusses various ways of reading observable data in a component and their characteristics. Predominately there are two ways to read observable data,

  1. Using the async pipe
  2. By subscribing to the observable using the subscribe() method

We will discuss both these options and their behavior corresponding to a particular change detection strategy.  To refresh, Angular has two Change Detection strategies

  1. default
  2. onPush

In the onPush strategy, Change Detection runs when a new reference is being passed to the component.

Fetching data from the API

Let us say we have an API that returns Product data as JSON, and we have a requirement to display the returned data in a component.  For understanding, the Product data looks like below,

pic 2

To work with the API data, first, we create an entity class as shown next, where each properties crosspond to the columns of data returned,



export class Product{

        public  ProductID : string;
        public  Title : string;
        public Price : number ;
        public Color : string;
        public inStock: string;
        public  Details: string;
        public Quantity: number;
        public Rating: number;
        public  ExpiryDate: string;
        public  ImageUrl: string;
    }


And after that, we create an Angular Service and inside service initially do the following tasks,

  • Inject HttpClient service
  • Configure HTTP header
  • Configure HTTP request options

These tasks can be done using the code listed below,



export class ProductService {

  // API URL
  apiurl = "https://localhost:44316/api/products";

  // Setting request headers to JSON
  headers = new HttpHeaders()
            .set('Content-Type', 'application/json')
            .set('Accept', 'application/json');

  httpOptions = {
    headers: this.headers
  };
  constructor(private http: HttpClient) { }

  // rest of the code ...
}


So far, we have created an HTTP Request Header and injected HttpClient Service. Next, to fetch data from the API, we perform HTTP GET operation.

The HttpClient service has a various method to perform various HTTP operations, among them, get method performs HTTP GET operation. We can use get method as shown next,



  getProducts(): Observable<Product[]> {
    return this.http.get<Product[]>(this.apiurl, this.httpOptions)
    .pipe(
      tap(data => {
        // debug here
        console.log(data);
      }),
      catchError(this.handleError)
    );
  }


The getProducts() function either returns an observable of product array or returns throwError observable.

The HttpClient service’s get method returns HttpResponse as observable with the response body is set to the request type. This means it does content negotiation with the API, and if Content-Type is set to JSON, it returns a response as JSON.

We have also used RxJS operators,

  • tap : to tap in the input stream and log the returned data
  • catchError : to handle the error in the HTTP request and throw an error as observable

The handeError function returns a creational function throwError, which creates a stream of the error.



 private handleError(error: any) {
    return throwError(error);
  }


So far, Angular services have a function in which we are making HTTP Request to the API and return HTTP response.  Putting everything together service will look like next code listing,



import { Injectable } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Product } from './product.enitity';
import { Observable, throwError } from 'rxjs';
import { tap, catchError } from 'rxjs/operators';

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

  // API URL
  apiurl = "https://localhost:44316/api/products";

  // Setting request headers to JSON
  headers = new HttpHeaders()
            .set('Content-Type', 'application/json')
            .set('Accept', 'application/json');

  httpOptions = {
    headers: this.headers
  };
  constructor(private http: HttpClient) { }

  getProducts(): Observable {
    return this.http.get(this.apiurl, this.httpOptions)
    .pipe(
      tap(data => {
        // debug error here
        console.log(data);
      }),
      catchError(this.handleError)
    );
  }

  private handleError(error: any) {
    return throwError(error);
  }

}


 

Using the subscribe() method

Everything good so far.  Now in the component class, to use ProductService first, you inject it and create variables to stored returned data



export class ProductsComponent implements OnInit, OnDestroy {

  products: Product[] ;
  productsubscription: Subscription;
  constructor(private productservice: ProductService) { }


The products variable will store returned data from the service, and productsubscription variable will store the observable.   Data can be read from the ProductService as shown in the next code listing.



getProducts() {
    this.productsubscription = this.productservice.getProducts().subscribe(
      (data) => {this.products = data;},
      (error) => { console.log(error) },
      () => { console.log(`products stream completed`); }
    );
  }


We are simply subscribing to the getProducts() method of the service and reading the returned data  in the products variable. We have also handled the error and complete functions by logging respective information.

Putting everything together the component class which subscribes to the HTTP response using a service looks like next code listing,



@Component({
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.css'],
  changeDetection:ChangeDetectionStrategy.Default
})
export class ProductsComponent implements OnInit, OnDestroy {

  products: Product[] ;
  productsubscription: Subscription;
  constructor(private productservice: ProductService) { }
  ngOnInit() {

    this.getProducts();
  }

  getProducts() {
    this.productsubscription = this.productservice.getProducts().subscribe(
      (data) => {this.products = data;},
      (error) => { console.log(error) },
      () => { console.log(`products stream completed`); }
    );
  }
  ngOnDestroy() {
    this.productsubscription.unsubscribe();
  }
}


A couple of important points worth discussing the ProductsComponent class are,

  • The Change Detection Strategy of the component is set to default
  • The component is explicitly unsubscribing to the observable in the ngOnDestroy() life cycle hook.
  • If the component subscribes to many observables, then we have to manually unsubscribe them, and not doing so may cause memory leaks and may have a performance impact

Keeping the above point in mind, implementation in the ProductComponent using the subscribe method does its task perfectly to read observable data from the service. On the template, data is displayed as shown next:




<h2>Product Loading .....</h2>

<div>
<table>
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Price</th>
<th>Color</th>
<th>Quanity</th>
<th>Rating</th>
<th>In Stock</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{p.ProductID}}</td>
<td>{{p.Title}}</td>
<td>{{p.Price}}</td>
<td>{{p.Color}}</td>
<td>{{p.Quantity}}</td>
<td>{{p.Rating}}</td>
<td>{{p.inStock}}</td>
</tr>
</tbody>
</table>
</div>

 

Everything is fine in the above implementation, and you should get data displayed in the table.

p3

So far, so good. Now go ahead and set component’s change detection strategy to onPush.

p4

Now you find that data is not displayed in the table, and instead of that you are getting Product Loading message.

p6

 

Since getProducts() does not return new reference and change detector is set to onPush, Angular does not run the change detector.  You can solve this by manually instructing Angular to run a change detector.  To do that,

  1. Inject ChangeDetectorRef service in the component
  2. Use markForCheck in the subscription method to instruct Angular to check the component by running the change detector.

p7

Now you will find data is rendered in the table again.   Above we are manually marking the component for the change and also manually unsubscribe when components get destroyed.

Advantages of subscribe() approach are,

  • Property can be used at the multiple places in the template
  • Property can be used at the multiple places in the component class
  • You can run custom business logic at the time of subscribing to the observable.

Some of the disadvantages are,

  • For the onPush change detection strategy, you have to explicitly mark component to run the change detector.
  • Explicitly unsubscribe the observables.

This approach may go out of hand when there are many observables used in the component. If we miss unsubscribing any observable, it may have potential memory leaks, etc. Nevertheless, putting everything together,



import { Component, OnInit, OnDestroy, ChangeDetectionStrategy, ChangeDetectorRef } from '@angular/core';
import { ProductService } from '../product.service';
import { Product } from '../product.enitity';
import { Observable, Subscription } from 'rxjs';

@Component({
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.css'],
  changeDetection:ChangeDetectionStrategy.OnPush
})
export class ProductsComponent implements OnInit, OnDestroy {
  products: Product[] ;
  productsubscription: Subscription;

  constructor(private productservice: ProductService,
               private cd: ChangeDetectorRef) { }

  getProducts() {
    this.productsubscription = this.productservice.getProducts().subscribe(
      (data) => {
        this.products = data;
        this.cd.markForCheck();
      },
      (error) => { console.log(error) },
      () => { console.log(`products stream completed`); }
    );
  }

  ngOnInit() {

    this.getProducts();
  }

  ngOnDestroy() {
    this.productsubscription.unsubscribe();
  }
}


 

Async pipe

The second or some people consider it a better approach is to work with observable data is by using async pipe.  To use async pipe,

  1. Declare a variable of observable type
  2. Call the service method which returns observable

First, declare a variable like below,



products$ : Observable;


and then make a call to the service,



  getProducts() {
     this.products$ = this.productservice.getProducts();
    }


And on the template, use an async pipe to display the observable data, as shown next




<h2>Product Loading .....</h2>

<div>
<table>
<thead>
<tr>
<th>Id</th>
<th>Title</th>
<th>Price</th>
<th>Color</th>
<th>Quanity</th>
<th>Rating</th>
<th>In Stock</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{p.ProductID}}</td>
<td>{{p.Title}}</td>
<td>{{p.Price}}</td>
<td>{{p.Color}}</td>
<td>{{p.Quantity}}</td>
<td>{{p.Rating}}</td>
<td>{{p.inStock}}</td>
</tr>
</tbody>
</table>
</div>

We used async pipe in *ngFor directive to display the observable data. Main advantages of using the async pipe are

  1. In onPush change detection strategy, if observable data changes it automatically marks component for the check.
  2. On component destruction, it automatically unsubscribes the observable hence avoids chances of any potential memory leak

Using the async pipe keeps code cleaner, and also you don’t need to manually run change detector for onPush Change Detection strategy.  To use async pipe component class will look like below,



import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { ProductService } from '../product.service';
import { Product } from '../product.enitity';
import { Observable, Subscription } from 'rxjs';

@Component({
  selector: 'app-products',
  templateUrl: './products.component.html',
  styleUrls: ['./products.component.css'],
  changeDetection:ChangeDetectionStrategy.OnPush
})
export class ProductsComponent implements OnInit {

  products$ : Observable;

  constructor(private productservice: ProductService) { }

  getProducts() {
     this.products$ = this.productservice.getProducts();
    }

  ngOnInit() {

    this.getProducts();
  }

}


Now, I hope you have a better understanding of when to use subscribe method approach and when to use async pipe.  So, to summarize let us revisit the diagram we shared in the beginning of this post,

dhananjay kumar

My suggestion is when in doubt use async pipe 😊. I hope you find this post useful. Thanks for reading.

 

I am an indepnedent Trainer and Consultant on Angular, JavaScript, Node, .NET Core, REST , GraphQL . To hire reach me at debugmode@outllook[dot]com or tweet me  @debug_mode

 

 

 

 

 

 

 

Simplest way to share data between two unrelated Components in Angular

In Angular, it is essential to know how components communicate with each other. If you use a component inside another component, they create a parent child relationship.  In such a scenario, parent and child components communicate to each other in following ways:

  • @Input()
  • @Output()
  • Temp Ref Variable
  • ViewChild and ContentChild

You can learn in detail about @Input here   and @Output here. In this blog post, you will learn how data can be shared between components that are not related to each other using Angular Service.

To understand this using an example, create a service.  In the service, create a variable called count.  Service will share value of count variable across the components. Before we create count variable, let us talk about requirement again. We want all components to access last updated value of the data shared using the service.

For this, we have to wrap the count variable in RxJS subjects. To be precise let us use BehaviorSubject.

We are using BehaviorSubject for the following reasons:

  1. Data from the service should be multicasted. Each consumer component should access the same copy of the data. For this purpose, BehaviorSubject is used.
  2. We are not using observables, as they are unicast in nature. Subscribers will have their own copy of data.
  3. BehaviorSubject stores current value. Therefore, component will always read current value of data stored in BehaviorSubject.

Read full article on the Infragistics blog

Simplifying Angular CLI for beginners

So you want to write your first Angular application, however setting up even a ‘Hello World’ Angular application is not easy. It requires many steps such as:

  • Setting up a TypeScript compiler, if you choose to use TypeScript
  • Configuration of Webpack or other module loader
  • Setting up local web development server
  • Installing and configuring dependencies
  • Configuring Unit Test environment
  • Configuring End to End Test environment
  • Working with Continuous Delivery
  • Working with Continuous Integration and many more

You can perform all these tasks manually, but this will require a strong understanding of all these concepts and will make starting a new project very time consuming. To solve this problem, Angular comes with the Angular Command Line Interface (CLI).

Learn more about it here: https://cli.angular.io/

All these tasks are taken care of by Angular CLI, which is a command line tool for creating, testing, and deploying Angular apps. It is recommended to use Angular CLI for creating Angular apps, as you do not need to spend time installing and configuring all the required dependencies and wiring everything together. It provides you with many boilerplates and saves your time.

It uses Webpack to include all the packaging, the loading module, importing functionality, BrowserLink and more. The entire Webpack configuration is done completely by CLI so you don’t have to worry about it. It also configures Jasmine and Karma for unit tests and TypeScript complier to transpile TypeScript file to JavaScript etc.  Let us see how we can work with Angular CLI.

Learn full article on the Infragistics blog

Video – Step by Step Component Communications in Angular

In Angular, components communicate to each other to share data such as object, string, number, array or html.

Parent and Child Components can communicate to each other in following ways

Parent and Child Components can communicate to each other in following ways

  • @Input()
  • @Output()
  • Temp Ref Variable
  • ViewChild and ContentChild

 

You can learn about these concepts in step by step video below.  If you like the video , do not forget to subscribe to our YouTube Channel for notification about future video tutorials.

 

 

 

You can read articles related to above video here :

Communication Between Components Using @Input() in Angular

Understanding @Output and EventEmitter in Angular

Free Download – Angular Essentials E-Book to help you getting started

Are you new to Angular and just starting with it? Well, I have written a small eBook for you, which you may find useful.

You can download it free from here

clip_image002

This book does not contain everything of Angular. It just contains topic you need to get started with Angular.

In these 10 pages E-Book, you will learn about:

  1. Angular’s basic architecture: NgModules, Components, Templates, Directives, Two-way Data Binding, Services, Dependency Injection, and Routing
  2. Setting up an environment: Downloading Angular with the Angular CLI tool; must have Node.js and npm installed
  3. Components: What you see in the browser. Consists of the following parts: a TypeScript class called the Component Class, an HTML file called the template of the component, and an optional CSS file for styling the component
  4. Data binding: Determines how data will flow in between the component class and component template
  5. Component communication: For sharing data (object, string, number, array, HTML)
  6. Directives: Creating DOM elements and changing their structure or behavior in an Angular application

Download it free from here

As I told you, this book is only 10 pages long and it contains basic minimum you need to get started with Angular. Currently I am writing a complete Angular Essentials Book, send me your feedback and I will try to incorporate them. You can reach me at debugmode[at]outlook[dot]com

I hope you find Angular Essentials Ref Card useful. Thanks!

Content Projection in Angular Element with Slot in Angular 7.0

In this article, we will learn how to project content in an Angular Element. If you are unfamiliar with the following,

  • Shadow Dom
  • ViewEncapsulation
  • Content Projection

I recommend you read the articles below before moving forward:

 

As of now, you know that we use ng-content to carry out content projection as shown in the next listing:

You can also project content as shown in the next listing:

The challenge with the above approach is, “If you use GreetComponent as your Angular Element,” you will not able to project content. To understand this better, let us start with converting GreetComponent to an Angular Element.  Here you can Learn Step by Step tp Create Angular Element.

After converting GreetComponent as Angular Element, AppModule should look like the listing below:

Now you can use GreetComponent on index.html as shown in the listing below:

Upon running the application, you will find that the <h2> element has not been projected to the Angular Element GreetComponent.

Read full article on the Infragistics blog

Simplifying Angular Data Binding to .NET Developers

Read full article on the Infragistics blog

At my job, I get the opportunity to talk to many .NET developers who want to learn Angular. Often, I’ve seen that they bring their .NET skills and work to map that in the learning of Angular. While the effort and drive to learn is there Angular is not .NET.

Since Angular is a pure JavaScript library, I’ll simplify basic but important concepts of Angular to .NET developers in this post series.  In this article, we’ll learn about Data Bindings in Angular. Luckily, Data Binding in Angular is much simpler than in .NET.

First, Let’s revise some of data binding techniques in .NET. For example, in ASP.NET MVC, you do data binding using a model. View is bound

  1. To an object
  2. To a complex object
  3. To a collection of objects

Essentially, in ASP.NET MVC, you do data binding to a model class. On the other hand, in WPF, you have data binding modes available. You can set the mode of data binding in XAML, as follows:

  1. One-way data binding
  2. Two-way data binding
  3. One-time data binding
  4. One-way to source data binding

If you are following MVVM patterns, then you might be using INotifyPropertyChanged interface to achieve two-way data binding. Therefore, there are many ways data bindings are achieved in world of .NET.

Data binding in Angular, however,  is much simpler.

If you are extremely new in Angular, then let me introduce you to Components. In Angular applications, what you see in the browser (or elsewhere) is a component. A component  consists of the following parts:

  1. A TypeScript class called Component class
  2. A HTML file called Template of the component
  3. An optional CSS file for the styling of the component

 

Read full article on the Infragistics blog

Angular Components: Pass by Reference or Pass by Value?

Read full article on the Infragistics blog

In Angular, you can pass data from parent component to child component using @Input() decorator, and a child component can emit an event to a parent comment using @Output() decorator.

The purpose of this blog post is to explain you whether it is pass by reference or pass by value in context of @Input() and @Output decorator.

To start with, let us assume that we have two components, as listed below:

As you see, we have two input properties.

  1. In data property, we will pass an object.
  2. In count property, we will pass a number.

From the AppComponent, we are passing value for both properties, as shown below:

As you see,  we are passing data (object) and count( number) to the child component. Since data is being passed as object,  it will be “Pass by Reference” and, since count is passed as number,  it will be “Pass by Value”.

Therefore, if passing an object, array, or the like,  then it is Pass by Reference, and for primitive types like number, it is Pass by Value.

Read full article on the Infragistics blog

Simplifying Different Types of Providers in Angular

An Angular Service provider delivers a runtime version of a dependency value. Therefore, when you inject a service, the Angular injector looks at the providers to create the instance of the service. It is the provider that determines which instance or value should be injected at the runtime in component, pipes, or directives. There are many jargons involved here, so to understand purpose of types of providers, let us start with creating a service. Let’s say we have a service called ErrorService, which is just logging the error message.

Now, we can use this service in a component, as shown in the listing below:

We are importing the service, passing it in the providers array, and injecting it in the constructor of component. We are calling the service method on click of the button, and you can see error message passed in the console. Very simple right?

Here, Angular will rely on the values passed in the providers array of component (or module) to find which instance should be injected at the run time.

“A Provider determines that how object of certain token can be created.”

So, when you pass a service name in providers array of either component or module, like below:

Here, Angular is going to use token value ErrorService and, for token ErrorService, it will create object of ErrorService class. The above syntax is a shortcut of the below syntax:

The provide property holds the token that serves as the key for

1. locating the dependency value.

2. registering the dependency.

The second property (it is of four types) is used to create the dependency value. There are four possible values of second parameter, as follows:

1. useClass

2. useExisting

3. useValue

4. useFactory

We just saw example of useClass. Now, consider a scenario that you have a new class for better error logging called NewErrorService.

useExisting

Now, we want that instead of the instance of ErrorService, the instance of NewErrorService should be injected. Also, ideally, both classes must be implementing the same Interface, which means they will have same method signatures with different implementation. So now, for the token ErrorService, we want the instance of NewErrorService to be injected. It can be done by using useClass, as shown below:

The problem with the above approach is that there will be two instances of NewErrorService. This can be resolved by the use of useExisting.

Now there will be only one instance of NewErrorService and for token ErrorService instance of NewErrorService will be created.

Read full article on the Infragistics blog