The most common use case will be for a component to directly inject a service into itself. Although the rhythms of defining service types and using dependency injection remain mostly the same, it's important to get a good hold of the fundamentals of Angular 2's dependency injection schema, as it differs in several important ways.
The code, links, and a live example of this are available at .
Suppose you had the following skeleton application:
[app/root.component.ts] import {Component} from '@angular/core'; @Component({ selector: 'root', template: ` <h1>root component!</h1> <button (click)="fillArticle()">Show article</button> <h2>{{title}}</h2> ` }) export class RootComponent { title:string; constructor() {} fillArticle() {} }
Your objective is to implement a service that can be injected into this component and return an article title to fill the template.
As you might expect, services in Angular 2 are represented as classes. Similar to components, services are designated as such with an @Injectable
decorator. Create this service in its own file:
[app/article.service.ts] import {Injectable} from '@angular/core'; @Injectable() export class ArticleService { private title_:string = ` CFO Yodels Quarterly Earnings Call, Stock Skyrockets ` }
This service has a private title that you need to transfer to the component, but first you must make the service itself available to the component. This can be done by importing the service, then listing it in the providers
property of the application module:
[app/app.module.ts] import {NgModule} from '@angular/core'; import {BrowserModule} from '@angular/platform-browser'; import {RootComponent} from './root.component'; import {ArticleService} from './article.service'; @NgModule({ imports: [ BrowserModule ], declarations: [ RootComponent ], providers: [ ArticleService ], bootstrap: [ RootComponent ] }) export class AppModule {}
Now that the service can be provided, inject it into the component:
[app/root.component.ts] import {Component} from '@angular/core'; import {ArticleService} from './article.service'; @Component({ selector: 'root', template: ` <h1>root component!</h1> <button (click)="fillArticle()">Show article</button> <h2>{{title}}</h2> ` }) export class RootComponent { title:string; constructor(private articleService_:ArticleService) {} fillArticle() {} }
This new code will create a new instance of ArticleService
when RootComponent
is instantiated, and then inject it into the constructor. Anything injected into a component will be available as a component instance member, which you can use to connect a service method to a component method:
[app/article.service.ts] import {Injectable} from '@angular/core'; @Injectable() export class ArticleService { private title_:string = ` CFO Yodels Quarterly Earnings Call, Stock Skyrockets `; getTitle() { return this.title_; } } [app/root.component.ts] import {Component} from '@angular/core'; import {ArticleService} from './article.service'; @Component({ selector: 'root', template: ` <h1>root component!</h1> <button (click)="fillArticle()">Show article</button> <h2>{{title}}</h2> ` }) export class RootComponent { title:string; constructor(private articleService_:ArticleService) {} fillArticle():void { this.title = this.articleService_.getTitle(); } }
Without the decorator, the service you have just built is rather plain in composition. With the @Injectable()
decoration, the class is designated to the Angular framework as one that will be injected elsewhere.
Designation as an injectable has a number of considerations that are importantly distinct from just being passed in parametrically. When is the injected class instantiated? How is it linked to the component instance? How are global and local instances controlled? These are all discussed in the more advanced recipes in this chapter.
Designation as an injectable service is only one piece of the puzzle. The component needs to be informed of the existence of the service. You must first import the service class into the component module, but this alone is not sufficient. Recall that the syntax used to inject a service was simply a way to list it as a constructor parameter. Behind the scenes, Angular is smart enough to recognize that these component arguments are to be injected, but it requires the final piece to connect the imported module to its place as an injected resource.
This final piece takes the form of the providers
property of the NgModule
definition. For the purpose of this recipe, it isn't important that you know the details of the property. In short, this array designates the articleService
constructor parameter as an injectable and identifies that ArticleService
should be injected into the constructor.
It's important to acknowledge here how the TypeScript decorators help the dependency injection setup. Decorators do not modify an instance of a class; rather, they modify the class definition. The NgModule
containing the providers list will be initialized prior to any instance of the actual component being instantiated. Thus, Angular will be aware of all the services that you might want to inject into the constructor.