How exactly does the service hierarchy work in this Angular 2 app?

I am very new to Angular 2 and I have the following question about services .

Into the main view (the one belonging to the app.component.ts class ). I have a situation like this:

<div class="container">
  <div class="row">
    <div class="col-xs-12 col-md-8 col-md-offset-2">
      <app-new-account (accountAdded)="onAccountAdded($event)"></app-new-account>
      <hr>
      <app-account
        *ngFor="let acc of accounts; let i = index"
        [account]="acc"
        [id]="i"
        (statusChanged)="onStatusChanged($event)"></app-account>
    </div>
  </div>
</div>

      

So, in this view, I have 2 helper components ( app-new-account and app-account ).

In the main AppComponent class , I have:

import {Component, OnInit} from '@angular/core';
import {AccountsService} from './accounts.service';

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

  accounts: {name: string, status: string}[] = [];

  // Injectiong the AccountsService:
  constructor(private accountsService: AccountsService) {}

  ngOnInit() {
    this.accounts = this.accountsService.accounts;
  }

}

      

Where I define AccountsService as a service of this line in the component decorator:

providers: [AccountsService]

      

From what I understand, it indicates that this AccountsService class should be registered as a service for the main AppComponent and for its entire subcomponent . strong>. Is this true or am I missing something?

So this means that the two subcomponent classes associated with the previous app-new-account and app-account tags are using the same AccountsService instance as a service?

Is this the reason, because I don't have AccountsService in the provider array of these two sub-patents ?

Is this my reason correct or am I missing something?

+1


source to share


1 answer


So, this means that the classes of the two subcomponents associated with the previous app-new-account and app-account tags are using the same instance of the AccountsService class as a service?

Yes. An injector is created for each instance of the component. Because the injector is hierarchical, all children of the component access the same service instance as the parent. If not , they define the service in their own array providers

using the same token . Here is the injector diagram:

// all components share the same instance
     AppComponentInjector
  providers: [AccountsService]
       /               \
      /                 \
 app-new-account     app-account

      


    // app-new-account has its own instance
             AppComponentInjector
          providers: [AccountsService]
           /                     \
          /                       \
   app-new-account                 app-account
   providers: [AccountsService]

      


     // every component has its own instance
         AppComponentInjector
      providers: [AccountsService]
       /                           \
      /                             \
  app-new-account                   app-account
  providers: [AccountsService]      providers: [AccountsService]

      

Host elements



I would also provide more details here, since in my opinion this is not clearly explained elsewhere. The injector is created on a component / directive node . This means that the directive creates its own injector on the host element it is hosted on.

So, if you put a directive with suppliers on an element hr

in your template AppComponent

:

<div class="container">
  <div class="row">
    <div class="col-xs-12 col-md-8 col-md-offset-2">
      <app-new-account (accountAdded)="onAccountAdded($event)"></app-new-account>
      <hr somedirectivewithproviders>  <----------------

      

You will have the following hierarchy:

  // all components and directives share the same instance
                AppComponentInjector
            providers: [AccountsService]
        /               |                  \
       /                |                   \
app-new-account somedirectivewithproviders   app-account

      

This means that if it somedirectivewithproviders

defines AccountsService

and injects it, it will receive a new instance as components. But the components will still get an instance from AppComponentInjector

:

  // all components and directives share the same instance
                    AppComponentInjector
                 providers: [AccountsService]
        /                      |                    \
       /                       |                     \
// gets same instance   //gets new own instance      // gets same instance   
 app-new-account      somedirectivewithproviders     app-account
                      providers: [AccountsService]

      

+5


source







All Articles