What are providers in Angular2?

AngularAngular2 Providers

Angular Problem Overview


In the Angular2 component configuration providers is one of the keys that we could specify. How are these providers defined and what are they used for?

@Component({
  ..
  providers: [..],
  ..
})

Note:

Angular2 documentation is gradually maturing but still sparse. It currently defines providers as:

> An array of dependency injection providers for services that the > component requires.

This recursive definition isn't very helpful. A more detailed explanation with an example would really help.

Angular Solutions


Solution 1 - Angular

Providers are usually singleton (one instance) objects, that other objects have access to through dependency injection (DI).

If you plan to use an object multiple times, for example, the Http service in different components, you can ask for the same instance of that service (reuse it). You do that with the help of DI by providing a reference to the same object that DI creates for you.

@Component){
  ..
  providers: [Http]
}

..instead of creating new object every time:

@Component){}
class Cmp {
  constructor() {
    // this is pseudo code, doens't work
    this.http = new Http(...options);
  }
}

This is an approximation, but that's the general idea behind Dependency Injection - let the framework handle creation and maintenance of reusable objects... Provider is Angular's term for these reusable objects (dependencies).

Solution 2 - Angular

Register injectables

Providers make injectables known to Angular's DI and define the scope of an injectable (service).

Hierarchy of injectors

Angular's DI creates a tree of injectors (parent > child > grandchild >...) that resembles the structure of your components and directives.

Single instance per provider

Providers are maintained per injector. Each provider provides a single instance of an injectable.

Provider lookup

When a component or directive has a dependency (constructor parameter), DI starts looking on this component's injector for providers. If it has one it requests the instance from this provider and injects it.

If the injector doesn't have a provider for the requested key (type) then the parent injector is visited, up to the root (bootstrap) until a provider is found and its instance can be injected. (If no provider is found DI throws an error).

Define the scope of an injectable instance

This way you can define the scope of a shared service, because DI starts looking from the component where an instance is requested upwards until it finds one.

Singleton or not

How many places you provide an injectable determines how many instances will be created (they are only instantiated if actually requested).

If you want a single instance for your whole application, then provide an injectable only once at the root component (or with bootstrap(AppComponent, [...]) which results in the same behavior.

If you want a new instance for each component A, then add it to providers of the component A.

(update) NgModule lazy and non-lazy

With the introduction of NgModule modules, additional levels were introduced. Providers registered with non-lazy-loaded modules are above the root component in the hierarchy.

Lazy-loaded modules are above the components and directives loaded by these components.

Because providers are read-only after an injector is created, there is no way to add providers from lazy loaded modules to the root injector. Therefore, lazy loaded modules get their own root scope.

See also https://stackoverflow.com/a/45231440/217408

Solution 3 - Angular

Think of providers like a recipe that tells angular how to inject a service.

We often declare providers in angular this way:

providers: [AnyService]

This is just a short hand for this:

[new Provider(AnyService, {useClass: AnyService})]

Both approaches are saying: Whenever someone requires "AnyService", provide the class "AnyService"

See that even though I'm providing the same class in the example above, in another scenario I could do something like this.

[new Provider(AnyService, {useClass: AnyServiceCustom})]

But in both scenarios, constructor would remain the same:

constructor( private _anyService: AnyService) {
}

To understand it better you need to understand how dependency injection works in Angular 2 as providers are directly related to it.

This is a must-read for every angular 2 developer.

https://angular.io/docs/ts/latest/guide/dependency-injection.html?The%20Provider%20class%20and%20provide%20function#!#injector-providers

Solution 4 - Angular

Add @Sasxa words, I want to point to Pro Angular book by Adam Freeman (chapter 20 (Using Service Providers)) for better, clear and detailed explanation with amazing examples.

Providers are classes that create and manage service objects the first time that Angular needs to resolve a dependency.Providers is used to register the classes to an angular module as a service.And then, this service classes can be used by other components during the itself creation phase in the module.

"Services are objects that provide common functionality to support other building blocks in an application, such as directives, components, and pipes. What’s important about services is the way that they are used, which is through a process called dependency injection. Using services can increase the flexibility and scalability of an Angular application, but dependency injection can be a difficult topic to understand." (Pro Angular (chapter 20))

Actually services can manage to distrubute objects as services using by dependency injection.

import { Injectable } from "@angular/core";

export enum LogLevel {DEBUG, INFO, ERROR}

    @Injectable()
    export class LogService {
      minimumLevel: LogLevel = LogLevel.INFO;
      logInfoMessage(message: string){
       this.logMessage(LogLevel.INFO, message);
      }
    }

@Component({
     selector: "example",
     templateUrl: "example.component.html"
})
export class exampleComponent {
    
  constructor(logService: LogService) {};
  //to do impl
}

import { NgModule }      from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
@NgModule({
  imports:      [ BrowserModule ],
  providers:    [ LogService ],
  declarations: [ ExampleComponent],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

Solution 5 - Angular

Providers are just the instance of the service.

You can create them once and use them everywhere or you can create multiple instances.

Let's understand how do we use them in Angular

All the services are registered with Angular but they can't be used until we instantiate them. So first, we have to instantiate the services and we do that by using providers.

There are two ways to instantiate the service. First by using providers array and the second one is to use providedIn.

The first method Using Providers Array

To use the service globally, we can place the providers in AppModule. By doing this, the instance of that service is created and all the components or other services in the app will use the same instance.

import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { NewService } from './newService';

@NgModule({
  declarations: [
    AppComponent
  ],
  providers: [NewService],
  bootstrap: [AppComponent]
})
export class AppModule { }

To use the service inside any specific component, we can place the providers in ComponentModule. By doing this, the new instance of that service is created and all the child components will use the same instance(It'll override the parent instance).

import { Component, OnInit } from '@angular/core';
import { NewService } from './newService';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss'],
  providers:[NewService]
})
export class AppComponent implements OnInit {
  constructor(private newService: newService) { }

  ngOnInit() { }
}

NOTE: If you place providers in AppComponent, then all the components in that app can use that instance but other services won't have access to that instance. To make other services also use the same instance, place it in AppModule.

The second method using providedIn

You can use Injectable decorator to instantiate any service.

import { Injectable } from '@angular/core';

@Injectable({
  providedIn: 'root' | Type<any>
})
export class UserService {
}

If it is root, then the whole application has access to that service. It means Angular creates a single instance of that service and whole application uses the same instance.

If it has to be accessed in only specific module, we can do that by giving the module name for providedIn

@Injectable({
   providedIn: AnyModule
})

One more advantage of using Injectable decorator to instantiate service is that, if the service is not at all used anywhere in that application, then it will not be there in compiled Angular Application.

Solution 6 - Angular

import { service_name} from '../path';

@Component({

  selector: 'selector_name',     
  templateUrl: './html file name ',
  styleUrls: ['./css file name '],
  providers: [ ./'service_name'];

})
export class AppComponent {

  constructor(private Service_name: service_name) { 
    //enter code here
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPranjal MittalView Question on Stackoverflow
Solution 1 - AngularSasxaView Answer on Stackoverflow
Solution 2 - AngularGünter ZöchbauerView Answer on Stackoverflow
Solution 3 - AngularDaniel PlisckiView Answer on Stackoverflow
Solution 4 - AngularfgulView Answer on Stackoverflow
Solution 5 - AngularNikhil YadavView Answer on Stackoverflow
Solution 6 - AngularVivek Kumar SahuView Answer on Stackoverflow