I have some settings which need to be available throughout my Angular 2 app. I understand the best way of handling this is to provide these values via a service, ensuring that the service is injected into the bootstrap()
method.
So my service (init.service.ts
) is like this:
import {Injectable} from 'angular2/core';
@Injectable()
export class InitService {
public static startNodeIdContent:number = 1053;
public static startNodeIdMedia:number = 9999;
}
Then my bootstrap method is like this:
import {bootstrap} from 'angular2/platform/browser'
import {ROUTER_PROVIDERS} from 'angular2/router';
import {AppComponent} from './app.component'
import {RouteNames} from './services/route-names.service';
import {InitService} from './services/init.service';
bootstrap(AppComponent, [ROUTER_PROVIDERS,RouteNames,InitService]);
Now, I need to make the startNodeIdContent
value available in a component, like this:
import { Component } from 'angular2/core';
import { HTTP_PROVIDERS } from 'angular2/http';
import { provide } from 'angular2/core';
import { Router } from 'angular2/router';
import { XHRBackend } from 'angular2/http';
import { RouteNames } from '../services/route-names.service';
import { ContentNode } from './content-node';
import { ContentService } from './content.service';
import { ContentTreeComponent } from './content-tree.component';
import { ContentDashboardComponent } from './content-dashboard.component';
@Component({
selector: 'my-dashboard',
template: `
<div class="tree-panel-container">
<div class="tree-panel-content">
<content-tree [startNodeId]="startNodeIdContent"></content-tree>
</div>
</div>
<content-dashboard></content-dashboard>
`,
directives: [ContentTreeComponent, ContentDashboardComponent],
providers: [
HTTP_PROVIDERS,
ContentService
]
})
export class ContentComponent {
constructor(private _routeNames:RouteNames, InitService){
_routeNames.name.next('Content');
}
startNodeIdContent = InitService.startNodeIdContent;
}
However, what I'm finding is that in this component, InitService
is not recognised. Do I have to still import the InitService
service into each component which consumes it? Part of me thinks that injecting it into the Bootstrap method should do this for me, but I'm unsure from the docs how exactly this should work.
Thanks.
A type name is just a meaningless string unless it is directly connected to the file where it is declared using an import. You application can contain or import an unlimited number of classes with the same name. Imports make it clear which class a type refers to.
Importing and providing/injecting are mostly unrelated concepts.
Importing is to make types known to the current source file and is a TypeScript concept. It's necessary for autocompletion, linting, .... Angulars DI uses the type of a constructor parameter as key to look up a provider. If the type is not canonicalized by an import, Angulars DI can't use it as key.
Providing is a concept of Angulars DI and defines the scope of a provider. DI looks upwards the hierarchical tree of injectors for a provider that matches the key (type) and then returns the instance from there.
You can use a string key or OpaqueToken
instead of a type
bootstrap(AppComponent, provide('InitService', {useClass: InitService});
to inject it like
constructor(@Inject('InitService') initService) {
// no auto-completion or type checking because of missing type information
}
but you'd miss on some advantages of type annotations.