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?
source to share
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]
source to share