Join the social network of Tech Nerds, increase skill rank, get work, manage projects...
 
  • NgModule.providers vs Component.providers vs Component.viewProviders in Angular 4

    • 0
    • 0
    • 0
    • 0
    • 0
    • 0
    • 3
    • 0
    • 2.08k
    Comment on it

    In Angular, concrete and runtime version of a dependency is provided by a provider. This dependency value(object) are then injected into components and services by injector. Therefore dependency need to be configured within providers otherwise injector will not be able to inject it. The configuration of Provider is via providers metadata. @NgModule() decorator as well as @Component() decorator contains providers metadata. 

     

    NgModule.providers 

     

    NgModule.providers are configured providers of @NgModule() decorator within module. Whenever providers configures a dependency(service) in application module then for all the components which are configured in declarations metadata of the @NgModule() decorator, the configured service will be available for dependency injection. 

     

    Example :-

     

    Consider a service "sharedservice"

     

    import { Injectable } from '@angular/core';
    
    @Injectable()
    export class sharedservice {
     value: string;
    }

     

    Consider two components parent and child component.

     

    ChildComponent

     

    import { Component, OnInit } from '@angular/core';
    import { sharedservice } from '../services/shared.service';
    
    @Component({
     selector: 'app-child',
     templateUrl: './child.component.html',
     styleUrls: ['./child.component.css']
    })
    export class ChildComponent implements OnInit {
    
     constructor(private service: sharedservice) { } // instance of sharedservice is injected in constructor
    
     ngOnInit() {
     }
    
    }

     

    child.component.html

     

    <div class="child">
     <p>Child</p>
     {{ service.value }}
    </div>

     

    Above ChildComponent html is just rendering the value of "value" property of sharedservice. 

     

    ParentComponent

     

    import { Component, OnInit } from '@angular/core';
    import { sharedservice } from '../services/shared.service';
    
    @Component({
     selector: 'app-parent',
     templateUrl: './parent.component.html',
     styleUrls: ['./parent.component.css'],
    })
    export class ParentComponent implements OnInit {
    
     constructor(private service: sharedservice) { } // instance of sharedservice is injected in constructor
    
     ngOnInit() {
     }
    }

     

    parent.component.html

     

    <div class="parent">
     <p>Parent</p>
     <form novalidate>
        <div class="form-group">
        <input type="text" class="form-control" name="value" [(ngModel)]="service.value">
       </div>
     </form>
     <app-child></app-child>
    </div>

     

    parent.component.html consist of an input box which is by using two way ngModel binding is reading and writing to value property of sharedservice.The ChildComponent is rendered inside ParentComponent 

     

    Consider a root component "app"

     

    AppComponent

     

    import { Component} from '@angular/core';
    
    @Component({
     selector: 'app-root',
     templateUrl: './app.component.html'
    })
    
    export class AppComponent{
    }
    

     

     app.component.html
     
     

    <div class="container">
    <div class="row">
     <div class="col-xs-4">
      <app-parent></app-parent>
     </div>
     <div class="col-xs-4">
      <app-parent></app-parent>
     </div>
    </div>
    </div>

     

    Two instances of ParentComponent "app-parent" are rendered side by side inside root component.

     

    App.module

     

    import { BrowserModule } from '@angular/platform-browser';
    import { NgModule } from '@angular/core';
    import { AppComponent } from './app.component';
    import { ParentComponent } from './parent/parent.component';
    import { ChildComponent } from './child/child.component';
    import { sharedservice } from './services/shared.service';
    import { FormsModule }  from '@angular/forms';
    
    @NgModule({
     declarations: [
      AppComponent,
      ParentComponent,
      ChildComponent
     ],
     imports: [
      BrowserModule, 
      FormsModule,
     ],
     providers: [sharedservice], //providers on NgModule
     bootstrap: [AppComponent]
    })
    export class AppModule { }

     

    index.html

     

    <!doctype html>
    <html lang="en">
    <head>
     <meta charset="utf-8">
     <title>AngularDemo</title>
     <base href="/">
    
     <meta name="viewport" content="width=device-width, initial-scale=1">
     <link rel="icon" type="image/x-icon" href="favicon.ico">
     <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
    </head>
    <body>
     <app-root></app-root>
    </body>
    </html>

     

    When above application runs

     

    Output :-

     

    Exaplanation :-


    In above example root NgModule is the root injector since the service is injected into it through providers property. Therefore, the service dependency is resolved by only one injector, whenever a request of an instance of sharedservice to be injected to one of component is made, it is always the injection of same instance. Above output is obtained since same instance of sharedservice is used everywhere, any changes made to input control in one of parent.component.html  automatically changes other input control and the child components. Configuration of providers into NgModule is sharing of one instance into entire application.
     

    Component.providers

     

    Component.providers are configured providers of @Component() decorator within component. Configuration of a service within a component providers metadata allows service availability for dependency injection in current component and its children components up to the bottom component. It is configuration of "sharedservice" through providers property on ParentComponent.

     

    ParentComponent is chaged to following

     

    import { Component, OnInit } from '@angular/core';
    import { sharedservice } from '../services/shared.service';
    
    @Component({
     selector: 'app-parent',
     templateUrl: './parent.component.html',
     styleUrls: ['./parent.component.css'],
     providers: [sharedservice]
    })
    export class ParentComponent implements OnInit {
    
     constructor(private service: sharedservice) { }
    
     ngOnInit() {
     }
    
    }

     

    When above application runs

     

    Output :-

     

    Explanation :

     

    In above output whenever we type in input control of one instance of ParentComponent make changes to only to its child components. Changes are not made to input control of other instance of ParentComponent and its child components since every ParentComponent has its own child injector with configuration of sharedservice i.e each instance of ParentComponent has separate instance of sharedservice the state of sharedservice is only shared between a ParentComponent and it’s child components not shared globally.

     

    Component.viewProviders


    Component.viewProviders are similar to Component.providers with the only difference that configured service will be available only in current component and its view children not in component content children.

     

     Following changes are made :-

     

    ParentComponent

     

    import { Component, OnInit } from '@angular/core';
    import { sharedservice } from '../services/shared.service';
    
    @Component({
     selector: 'app-parent',
     templateUrl: './parent.component.html',
     styleUrls: ['./parent.component.css'],
     viewProviders: [sharedservice]  //component viewprovider
    })
    export class ParentComponent implements OnInit {
    
     constructor(private service: sharedservice) { }
    
     ngOnInit() {
     }
    
    }


    parent.component.html

     

    <div class="parent">
     <p>Parent</p>
     <form novalidate>
        <div class="form-group">
        <input type="text" class="form-control" name="value" [(ngModel)]="service.value">
       </div>
     </form>
     <ng-content></ng-content> //content child
    </div>


    app.component.html

     

    <div class="container">
    <div class="row">
     <div class="col-xs-4">
      <app-parent><app-child></app-child></app-parent>
     </div>
     <div class="col-xs-4">
      <app-parent><app-child></app-child></app-parent>
     </div>
    </div>
    </div>

     

    When above application runs

     

    Output:-

     

    Exaplanation :-

     

    In above example ChildComponent now behave as content children instead of view children. Component whenever uses viewProviders property, an injector is created by component which can only be shared between component and its view children and not to its content children. 

    NgModule.providers vs Component.providers vs Component.viewProviders in Angular 4

 0 Comment(s)

Sign In
                           OR                           
                           OR                           
Register

Sign up using

                           OR                           
Forgot Password
Fill out the form below and instructions to reset your password will be emailed to you:
Reset Password
Fill out the form below and reset your password: