| 
									
										
										
										
											2016-08-08 15:48:45 -07:00
										 |  |  | block includes | 
					
						
							|  |  |  |   include ../_util-fns | 
					
						
							|  |  |  |   - var _thisDot = 'this.'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   **Dependency injection** is an important application design pattern. | 
					
						
							|  |  |  |   Angular has its own dependency injection framework, and | 
					
						
							|  |  |  |   we really can't build an Angular application without it. | 
					
						
							|  |  |  |   It's used so widely that almost everyone just calls it _DI_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   In this chapter we'll learn what DI is and why we want it. | 
					
						
							|  |  |  |   Then we'll learn [how to use it](#angular-di) in an Angular app. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   - [Why dependency injection?](#why-dependency-injection) | 
					
						
							|  |  |  |   - [Angular dependency injection](#angular-dependency-injection) | 
					
						
							|  |  |  |   - [Injector providers](#injector-providers) | 
					
						
							|  |  |  |   - [Dependency injection tokens](#dependency-injection-tokens) | 
					
						
							|  |  |  |   - [Summary](#summary) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Run the <live-example></live-example>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-main-section#why-di | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## Why dependency injection? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Let's start with the following code. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/car/car-no-di.ts', 'car', 'app/car/car.ts (without DI)') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Our `Car` creates everything it needs inside its constructor. | 
					
						
							|  |  |  |   What's the problem? | 
					
						
							|  |  |  |   The problem is that our `Car` class is brittle, inflexible, and hard to test. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Our `Car` needs an engine and tires. Instead of asking for them, | 
					
						
							|  |  |  |   the `Car` constructor instantiates its own copies from | 
					
						
							|  |  |  |   the very specific classes `Engine` and `Tires`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   What if the `Engine` class evolves and its constructor requires a parameter? | 
					
						
							|  |  |  |   Our `Car` is broken and stays broken until we rewrite it along the lines of | 
					
						
							|  |  |  |   `#{_thisDot}engine = new Engine(theNewParameter)`. | 
					
						
							|  |  |  |   We didn't care about `Engine` constructor parameters when we first wrote `Car`. | 
					
						
							|  |  |  |   We don't really care about them now. | 
					
						
							|  |  |  |   But we'll *have* to start caring because | 
					
						
							|  |  |  |   when the definition of `Engine` changes, our `Car` class must change. | 
					
						
							|  |  |  |   That makes `Car` brittle. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   What if we want to put a different brand of tires on our `Car`? Too bad. | 
					
						
							|  |  |  |   We're locked into whatever brand the `Tires` class creates. That makes our `Car` inflexible. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Right now each new car gets its own engine. It can't share an engine with other cars. | 
					
						
							|  |  |  |   While that makes sense for an automobile engine, | 
					
						
							|  |  |  |   we can think of other dependencies that should be shared, such as the onboard | 
					
						
							|  |  |  |   wireless connection to the manufacturer's service center. Our `Car` lacks the flexibility | 
					
						
							|  |  |  |   to share services that have been created previously for other consumers. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   When we write tests for our `Car` we're at the mercy of its hidden dependencies. | 
					
						
							|  |  |  |   Is it even possible to create a new `Engine` in a test environment? | 
					
						
							|  |  |  |   What does `Engine`itself depend upon? What does that dependency depend on? | 
					
						
							|  |  |  |   Will a new instance of `Engine` make an asynchronous call to the server? | 
					
						
							|  |  |  |   We certainly don't want that going on during our tests. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   What if our `Car` should flash a warning signal when tire pressure is low? | 
					
						
							|  |  |  |   How do we confirm that it actually does flash a warning | 
					
						
							|  |  |  |   if we can't swap in low-pressure tires during the test? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We have no control over the car's hidden dependencies. | 
					
						
							|  |  |  |   When we can't control the dependencies, a class becomes difficult to test. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   How can we make `Car` more robust, flexible, and testable? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   <a id="ctor-injection"></a> | 
					
						
							|  |  |  |   That's super easy. We change our `Car` constructor to a version with DI: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeTabs( | 
					
						
							|  |  |  |   'dependency-injection/ts/app/car/car.ts, dependency-injection/ts/app/car/car-no-di.ts', | 
					
						
							|  |  |  |   'car-ctor, car-ctor', | 
					
						
							|  |  |  |   'app/car/car.ts (excerpt with DI), app/car/car.ts (excerpt without DI)')(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   See what happened? We moved the definition of the dependencies to the constructor. | 
					
						
							|  |  |  |   Our `Car` class no longer creates an engine or tires. | 
					
						
							|  |  |  |   It just consumes them. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block ctor-syntax | 
					
						
							|  |  |  |   .l-sub-section | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       We also leveraged TypeScript's constructor syntax for declaring | 
					
						
							|  |  |  |       parameters and properties simultaneously. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Now we create a car by passing the engine and tires to the constructor. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/car/car-creations.ts', 'car-ctor-instantiation', '')(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   How cool is that? | 
					
						
							|  |  |  |   The definition of the engine and tire dependencies are | 
					
						
							|  |  |  |   decoupled from the `Car` class itself. | 
					
						
							|  |  |  |   We can pass in any kind of engine or tires we like, as long as they | 
					
						
							|  |  |  |   conform to the general API requirements of an engine or tires. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   If someone extends the `Engine` class, that is not `Car`'s problem. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     The _consumer_ of `Car` has the problem. The consumer must update the car creation code to | 
					
						
							|  |  |  |     something like this: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   - var stylePattern = { otl: /(new Car.*$)/gm }; | 
					
						
							|  |  |  |   +makeExample('dependency-injection/ts/app/car/car-creations.ts', 'car-ctor-instantiation-with-param', '', stylePattern)(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     The critical point is this: `Car` itself did not have to change. | 
					
						
							|  |  |  |     We'll take care of the consumer's problem soon enough. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   The `Car` class is much easier to test because we are in complete control | 
					
						
							|  |  |  |   of its dependencies. | 
					
						
							|  |  |  |   We can pass mocks to the constructor that do exactly what we want them to do | 
					
						
							|  |  |  |   during each test: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - var stylePattern = { otl: /(new Car.*$)/gm }; | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/car/car-creations.ts', 'car-ctor-instantiation-with-mocks', '', stylePattern)(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   **We just learned what dependency injection is**. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   It's a coding pattern in which a class receives its dependencies from external | 
					
						
							|  |  |  |   sources rather than creating them itself. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Cool! But what about that poor consumer? | 
					
						
							|  |  |  |   Anyone who wants a `Car` must now | 
					
						
							|  |  |  |   create all three parts: the `Car`, `Engine`, and `Tires`. | 
					
						
							|  |  |  |   The `Car` class shed its problems at the consumer's expense. | 
					
						
							|  |  |  |   We need something that takes care of assembling these parts for us. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We could write a giant class to do that: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/car/car-factory.ts', null, 'app/car/car-factory.ts') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   It's not so bad now with only three creation methods. | 
					
						
							|  |  |  |   But maintaining it will be hairy as the application grows. | 
					
						
							|  |  |  |   This factory is going to become a huge spiderweb of | 
					
						
							|  |  |  |   interdependent factory methods! | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Wouldn't it be nice if we could simply list the things we want to build without | 
					
						
							|  |  |  |   having to define which dependency gets injected into what? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This is where the dependency injection framework comes into play. | 
					
						
							|  |  |  |   Imagine the framework had something called an _injector_. | 
					
						
							|  |  |  |   We register some classes with this injector, and it figures out how to create them. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   When we need a `Car`, we simply ask the injector to get it for us and we're good to go. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/car/car-injector.ts','injector-call')(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Everyone wins. The `Car` knows nothing about creating an `Engine` or `Tires`. | 
					
						
							|  |  |  |   The consumer knows nothing about creating a `Car`. | 
					
						
							|  |  |  |   We don't have a gigantic factory class to maintain. | 
					
						
							|  |  |  |   Both `Car` and consumer simply ask for what they need and the injector delivers. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This is what a **dependency injection framework** is all about. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Now that we know what dependency injection is and appreciate its benefits, | 
					
						
							|  |  |  |   let's see how it is implemented in Angular. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-main-section#angular-di | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## Angular dependency injection | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Angular ships with its own dependency injection framework. This framework can also be used | 
					
						
							|  |  |  |   as a standalone module by other applications and frameworks. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   That sounds nice. What does it do for us when building components in Angular? | 
					
						
							|  |  |  |   Let's see, one step at a time. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We'll begin with a simplified version of the `HeroesComponent` | 
					
						
							|  |  |  |   that we built in the [The Tour of Heroes](../tutorial/). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeTabs( | 
					
						
							|  |  |  |   `dependency-injection/ts/app/heroes/heroes.component.1.ts, | 
					
						
							|  |  |  |   dependency-injection/ts/app/heroes/hero-list.component.1.ts, | 
					
						
							|  |  |  |   dependency-injection/ts/app/heroes/hero.ts, | 
					
						
							|  |  |  |   dependency-injection/ts/app/heroes/mock-heroes.ts`, | 
					
						
							|  |  |  |   'v1,,,', | 
					
						
							|  |  |  |   `app/heroes/heroes.component.ts, | 
					
						
							|  |  |  |   app/heroes/hero-list.component.ts, | 
					
						
							|  |  |  |   app/heroes/hero.ts, | 
					
						
							|  |  |  |   app/heroes/mock-heroes.ts`) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   The `HeroesComponent` is the root component of the *Heroes* feature area. | 
					
						
							|  |  |  |   It governs all the child components of this area. | 
					
						
							|  |  |  |   Our stripped down version has only one child, `HeroListComponent`, | 
					
						
							|  |  |  |   which displays a list of heroes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Right now `HeroListComponent` gets heroes from `HEROES`, an in-memory collection | 
					
						
							|  |  |  |   defined in another file. | 
					
						
							|  |  |  |   That may suffice in the early stages of development, but it's far from ideal. | 
					
						
							|  |  |  |   As soon as we try to test this component or want to get our heroes data from a remote server, | 
					
						
							|  |  |  |   we'll have to change the implementation of `heroes` and | 
					
						
							|  |  |  |   fix every other use of the `HEROES` mock data. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Let's make a service that hides how we get hero data. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Given that the service is a | 
					
						
							|  |  |  |     [separate concern](https://en.wikipedia.org/wiki/Separation_of_concerns), | 
					
						
							|  |  |  |     we suggest that you | 
					
						
							|  |  |  |     write the service code in its own file. | 
					
						
							|  |  |  |   +ifDocsFor('ts') | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       See [this note](#one-class-per-file) for details. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/heroes/hero.service.1.ts',null, 'app/heroes/hero.service.ts' ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Our `HeroService` exposes a `getHeroes` method that returns | 
					
						
							|  |  |  |   the same mock data as before, but none of its consumers need to know that. | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Notice the `@Injectable()` #{_decorator} above the service class. | 
					
						
							|  |  |  |     We'll discuss its purpose [shortly](#injectable). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - var _perhaps = _docsFor == 'dart' ? '' : 'perhaps'; | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     We aren't even pretending this is a real service. | 
					
						
							|  |  |  |     If we were actually getting data from a remote server, the API would have to be  | 
					
						
							|  |  |  |     asynchronous, #{_perhaps} returning a !{_PromiseLinked}. | 
					
						
							|  |  |  |     We'd also have to rewrite the way components consume our service. | 
					
						
							|  |  |  |     This is important in general, but not to our current story. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-11-17 14:10:28 -08:00
										 |  |  |   A service is nothing more than a class in Angular. | 
					
						
							| 
									
										
										
										
											2016-08-08 15:48:45 -07:00
										 |  |  |   It remains nothing more than a class until we register it with an Angular injector. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #bootstrap | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Configuring the injector | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We don't have to create an Angular injector. | 
					
						
							|  |  |  |   Angular creates an application-wide injector for us during the bootstrap process. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/main.ts', 'bootstrap', 'app/main.ts (excerpt)')(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   We do have to configure the injector by registering the **providers** | 
					
						
							|  |  |  |   that create the services our application requires. | 
					
						
							|  |  |  |   We'll explain what [providers](#providers) are later in this chapter. | 
					
						
							|  |  |  |   Before we do, let's see an example of provider registration during bootstrapping: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/main.1.ts', 'bootstrap-discouraged')(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   The injector now knows about our `HeroService`. | 
					
						
							|  |  |  |   An instance of our `HeroService` will be available for injection across our entire application. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Of course we can't help wondering about that comment telling us not to do it this way. | 
					
						
							|  |  |  |   It *will* work. It's just not a best practice. | 
					
						
							|  |  |  |   The bootstrap provider option is intended for configuring and overriding Angular's own | 
					
						
							|  |  |  |   preregistered services, such as its routing support. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The preferred approach is to register application providers in application components. | 
					
						
							|  |  |  |   Because the `HeroService` is used within the *Heroes* feature area — | 
					
						
							|  |  |  |   and nowhere else — the ideal place to register it is in the top-level `HeroesComponent`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Registering providers in a component | 
					
						
							|  |  |  |   Here's a revised `HeroesComponent` that registers the `HeroService`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - var stylePattern = { otl: /(providers:.*),/ }; | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/heroes/heroes.component.1.ts', 'full','app/heroes/heroes.component.ts', stylePattern)(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Look closely at the `providers` part of the `@Component` metadata. | 
					
						
							|  |  |  |   An instance of the `HeroService` is now available for injection in this `HeroesComponent` | 
					
						
							|  |  |  |   and all of its child components. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The `HeroesComponent` itself doesn't happen to need the `HeroService`. | 
					
						
							|  |  |  |   But its child `HeroListComponent` does, so we head there next. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Preparing the HeroListComponent for injection | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The `HeroListComponent` should get heroes from the injected `HeroService`. | 
					
						
							|  |  |  |   Per the dependency injection pattern, the component must ask for the service in its  | 
					
						
							|  |  |  |   constructor, [as we explained earlier](#ctor-injection). | 
					
						
							|  |  |  |   It's a small change: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeTabs( | 
					
						
							|  |  |  |   `dependency-injection/ts/app/heroes/hero-list.component.2.ts, | 
					
						
							|  |  |  |   dependency-injection/ts/app/heroes/hero-list.component.1.ts`, | 
					
						
							|  |  |  |   null, | 
					
						
							|  |  |  |   `app/heroes/hero-list.component (with DI), | 
					
						
							|  |  |  |    app/heroes/hero-list.component (without DI)`) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     #### Focus on the constructor | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Adding a parameter to the constructor isn't all that's happening here. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   +makeExample('dependency-injection/ts/app/heroes/hero-list.component.2.ts', 'ctor')(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Note that the constructor parameter has the type `HeroService`, and that | 
					
						
							|  |  |  |     the `HeroListComponent` class has an `@Component` #{_decorator} | 
					
						
							|  |  |  |     (scroll up to confirm that fact). | 
					
						
							|  |  |  |     Also recall that the parent component (`HeroesComponent`) | 
					
						
							|  |  |  |     has `providers` information for `HeroService`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The constructor parameter type, the `@Component` #{_decorator}, | 
					
						
							|  |  |  |     and the parent's `providers` information combine to tell the | 
					
						
							|  |  |  |     Angular injector to inject an instance of | 
					
						
							|  |  |  |     `HeroService` whenever it creates a new `HeroListComponent`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #di-metadata | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Implicit injector creation | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   When we introduced the idea of an injector above, we showed how to | 
					
						
							|  |  |  |   use it to create a new `Car`. Here we also show how such an injector | 
					
						
							|  |  |  |   would be explicitly created: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/car/car-injector.ts','injector-create-and-call')(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   We won't find code like that in the Tour of Heroes or any of our other samples. | 
					
						
							|  |  |  |   We *could* write code that [explicitly creates an injector](#explicit-injector) if we *had* to, but we rarely do. | 
					
						
							|  |  |  |   Angular takes care of creating and calling injectors | 
					
						
							|  |  |  |   when it creates components for us — whether through HTML markup, as in `<hero-list></hero-list>`, | 
					
						
							|  |  |  |   or after navigating to a component with the [router](./router.html). | 
					
						
							|  |  |  |   If we let Angular do its job, we'll enjoy the benefits of automated dependency injection. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Singleton services | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Dependencies are singletons within the scope of an injector. | 
					
						
							|  |  |  |   In our example, a single `HeroService` instance is shared among the | 
					
						
							|  |  |  |   `HeroesComponent` and its `HeroListComponent` children. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   However, Angular DI is an hierarchical injection | 
					
						
							|  |  |  |   system, which means that nested injectors can create their own service instances. | 
					
						
							|  |  |  |   Learn more about that in the [Hierarchical Injectors](./hierarchical-dependency-injection.html) chapter. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Testing the component | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We emphasized earlier that designing a class for dependency injection makes the class easier to test. | 
					
						
							|  |  |  |   Listing dependencies as constructor parameters may be all we need to test application parts effectively. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   For example, we can create a new `HeroListComponent` with a mock service that we can manipulate | 
					
						
							|  |  |  |   under test: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/test.component.ts', 'spec')(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							| 
									
										
										
										
											2016-11-05 12:18:03 -07:00
										 |  |  |     Learn more in [Testing](./testing.html). | 
					
						
							| 
									
										
										
										
											2016-08-08 15:48:45 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### When the service needs a service | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Our `HeroService` is very simple. It doesn't have any dependencies of its own. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   What if it had a dependency? What if it reported its activities through a logging service? | 
					
						
							|  |  |  |   We'd apply the same *constructor injection* pattern, | 
					
						
							|  |  |  |   adding a constructor that takes a `Logger` parameter. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Here is the revision compared to the original. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeTabs( | 
					
						
							|  |  |  |   `dependency-injection/ts/app/heroes/hero.service.2.ts, | 
					
						
							|  |  |  |   dependency-injection/ts/app/heroes/hero.service.1.ts`, | 
					
						
							|  |  |  |   null, | 
					
						
							|  |  |  |   `app/heroes/hero.service (v2), | 
					
						
							|  |  |  |   app/heroes/hero.service (v1)`) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   The constructor now asks for an injected instance of a `Logger` and stores it in a private property called `#{_priv}logger`. | 
					
						
							|  |  |  |   We call that property within our `getHeroes` method when anyone asks for heroes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //- FIXME refer to Dart API when that page becomes available. | 
					
						
							| 
									
										
										
										
											2016-11-08 08:21:02 -08:00
										 |  |  | - var injUrl = '../api/core/index/Injectable-decorator.html'; | 
					
						
							| 
									
										
										
										
											2016-08-08 15:48:45 -07:00
										 |  |  | h3#injectable Why @Injectable()? | 
					
						
							|  |  |  | :marked | 
					
						
							| 
									
										
										
										
											2016-11-08 08:21:02 -08:00
										 |  |  |   **<a href="#{injUrl}">@Injectable()</a>** marks a class as available to an | 
					
						
							| 
									
										
										
										
											2016-08-08 15:48:45 -07:00
										 |  |  |   injector for instantiation. Generally speaking, an injector will report an | 
					
						
							|  |  |  |   error when trying to instantiate a class that is not marked as | 
					
						
							|  |  |  |   `@Injectable()`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block injectable-not-always-needed-in-ts | 
					
						
							|  |  |  |   .l-sub-section | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       As it happens, we could have omitted `@Injectable()` from our first | 
					
						
							|  |  |  |       version of `HeroService` because it had no injected parameters. | 
					
						
							|  |  |  |       But we must have it now that our service has an injected dependency. | 
					
						
							|  |  |  |       We need it because Angular requires constructor parameter metadata  | 
					
						
							|  |  |  |       in order to inject a `Logger`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   .callout.is-helpful | 
					
						
							|  |  |  |     header Suggestion: add @Injectable() to every service class | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       We recommend adding `@Injectable()` to every service class, even those that don't have dependencies | 
					
						
							|  |  |  |       and, therefore, do not technically require it. Here's why: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ul(style="font-size:inherit") | 
					
						
							|  |  |  |       li <b>Future proofing:</b> No need to remember <code>@Injectable()</code> when we add a dependency later. | 
					
						
							|  |  |  |       li <b>Consistency:</b> All services follow the same rules, and we don't have to wonder why #{_a} #{_decorator} is missing. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Injectors are also responsible for instantiating components | 
					
						
							|  |  |  |   like `HeroesComponent`. Why haven't we marked `HeroesComponent` as | 
					
						
							|  |  |  |   `@Injectable()`? | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We *can* add it if we really want to. It isn't necessary because the | 
					
						
							|  |  |  |   `HeroesComponent` is already marked with `@Component`, and this | 
					
						
							|  |  |  |   !{_decorator} class (like `@Directive` and `@Pipe`, which we'll learn about later) | 
					
						
							| 
									
										
										
										
											2016-11-08 08:21:02 -08:00
										 |  |  |   is a subtype of <a href="#{injUrl}">Injectable</a>.  It is in | 
					
						
							|  |  |  |   fact `Injectable` #{_decorator}s that | 
					
						
							| 
									
										
										
										
											2016-08-08 15:48:45 -07:00
										 |  |  |   identify a class as a target for instantiation by an injector. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +ifDocsFor('ts') | 
					
						
							|  |  |  |   .l-sub-section | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       At runtime, injectors can read class metadata in the transpiled JavaScript code | 
					
						
							|  |  |  |       and use the constructor parameter type information | 
					
						
							|  |  |  |       to determine what things to inject.  | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       Not every JavaScript class has metadata. | 
					
						
							|  |  |  |       The TypeScript compiler discards metadata by default. | 
					
						
							|  |  |  |       If the `emitDecoratorMetadata` compiler option is true  | 
					
						
							|  |  |  |       (as it should be in the `tsconfig.json`), | 
					
						
							|  |  |  |       the compiler adds the metadata to the generated JavaScript  | 
					
						
							|  |  |  |       for _every class with at least one decorator_. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       While any decorator will trigger this effect, mark the service class with the | 
					
						
							| 
									
										
										
										
											2016-11-08 08:21:02 -08:00
										 |  |  |       <a href="#{injUrl}">Injectable</a> #{_decorator} | 
					
						
							| 
									
										
										
										
											2016-08-08 15:48:45 -07:00
										 |  |  |       to make the intent clear. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .callout.is-critical | 
					
						
							|  |  |  |   header Always include the parentheses | 
					
						
							|  |  |  |   block always-include-paren | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       Always write `@Injectable()`, not just `@Injectable`. | 
					
						
							|  |  |  |       Our application will fail mysteriously if we forget the parentheses. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-main-section#logger-service | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## Creating and registering a logger service | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We're injecting a logger into our `HeroService` in two steps: | 
					
						
							|  |  |  |   1. Create the logger service. | 
					
						
							|  |  |  |   1. Register it with the application. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Our logger service is quite simple: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/logger.service.ts', null, 'app/logger.service.ts') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block real-logger | 
					
						
							|  |  |  |   //- N/A | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   We're likely to need the same logger service everywhere in our application, | 
					
						
							|  |  |  |   so we put it in the project's `#{_appDir}` folder, and | 
					
						
							|  |  |  |   we register it in the `providers` #{_array} of the metadata for our application root component, `AppComponent`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExcerpt('app/providers.component.ts','providers-logger','app/app.component.ts (excerpt)') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   If we forget to register the logger, Angular throws an exception when it first looks for the logger: | 
					
						
							|  |  |  | code-example(format="nocode"). | 
					
						
							|  |  |  |   EXCEPTION: No provider for Logger! (HeroListComponent -> HeroService -> Logger) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   That's Angular telling us that the dependency injector couldn't find the *provider* for the logger. | 
					
						
							|  |  |  |   It needed that provider to create a `Logger` to inject into a new | 
					
						
							|  |  |  |   `HeroService`, which it needed to | 
					
						
							|  |  |  |   create and inject into a new `HeroListComponent`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The chain of creations started with the `Logger` provider. *Providers* are the subject of our next section. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-main-section#providers | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## Injector providers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   A provider *provides* the concrete, runtime version of a dependency value. | 
					
						
							|  |  |  |   The injector relies on **providers** to create instances of the services | 
					
						
							|  |  |  |   that the injector injects into components and other services. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We must register a service *provider* with the injector, or it won't know how to create the service. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Earlier we registered the `Logger` service in the `providers` #{_array} of the metadata for the `AppComponent` like this: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','providers-logger') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - var implements = _docsFor == 'dart' ? 'implements' : 'looks and behaves like a ' | 
					
						
							|  |  |  | - var objectlike = _docsFor == 'dart' ? '' : 'an object that behaves like ' | 
					
						
							|  |  |  | - var loggerlike = _docsFor == 'dart' ? '' : 'We could provide a logger-like object. ' | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   There are many ways to *provide* something that #{implements} `Logger`. | 
					
						
							|  |  |  |   The `Logger` class itself is an obvious and natural provider. | 
					
						
							|  |  |  |   But it's not the only way. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We can configure the injector with alternative providers that can deliver #{objectlike} a `Logger`. | 
					
						
							|  |  |  |   We could provide a substitute class. #{loggerlike} | 
					
						
							|  |  |  |   We could give it a provider that calls a logger factory function. | 
					
						
							|  |  |  |   Any of these approaches might be a good choice under the right circumstances. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   What matters is that the injector has a provider to go to when it needs a `Logger`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //- Dart limitation: the provide function isn't const so it cannot be used in an annotation. | 
					
						
							|  |  |  | - var _andProvideFn = _docsFor == 'dart' ? '' : 'and <i>provide</i> object literal'; | 
					
						
							|  |  |  | #provide | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### The *Provider* class !{_andProvideFn} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   We wrote the `providers` #{_array} like this: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','providers-1') | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-08-24 14:46:06 -07:00
										 |  |  | block provider-shorthand | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     This is actually a shorthand expression for a provider registration | 
					
						
							| 
									
										
										
										
											2016-08-08 15:48:45 -07:00
										 |  |  |     using a _provider_ object literal with two properties: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','providers-3') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block provider-ctor-args | 
					
						
							|  |  |  |   - var _secondParam = 'provider definition object'; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   The first is the [token](#token) that serves as the key for both locating a dependency value | 
					
						
							|  |  |  |   and registering the provider. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The second is a !{_secondParam},  | 
					
						
							|  |  |  |   which we can think of as a *recipe* for creating the dependency value.  | 
					
						
							|  |  |  |   There are many ways to create dependency values ... and many ways to write a recipe. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #class-provider | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Alternative class providers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Occasionally we'll ask a different class to provide the service. | 
					
						
							|  |  |  |   The following code tells the injector | 
					
						
							|  |  |  |   to return a `BetterLogger` when something asks for the `Logger`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','providers-4') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block dart-diff-const-metadata | 
					
						
							|  |  |  |   //- N/A | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Class provider with dependencies | 
					
						
							|  |  |  |   Maybe an `EvenBetterLogger` could display the user name in the log message. | 
					
						
							|  |  |  |   This logger gets the user from the injected `UserService`, | 
					
						
							|  |  |  |   which happens also to be injected at the application level. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','EvenBetterLogger')(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Configure it like we did `BetterLogger`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','providers-5')(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Aliased class providers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Suppose an old component depends upon an `OldLogger` class. | 
					
						
							|  |  |  |   `OldLogger` has the same interface as the `NewLogger`, but for some reason | 
					
						
							|  |  |  |   we can't update the old component to use it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   When the *old* component logs a message with `OldLogger`, | 
					
						
							|  |  |  |   we want the singleton instance of `NewLogger` to handle it instead. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The dependency injector should inject that singleton instance | 
					
						
							|  |  |  |   when a component asks for either the new or the old logger. | 
					
						
							|  |  |  |   The `OldLogger` should be an alias for `NewLogger`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We certainly do not want two different `NewLogger` instances in our app. | 
					
						
							|  |  |  |   Unfortunately, that's what we get if we try to alias `OldLogger` to `NewLogger` with `useClass`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','providers-6a')(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   The solution: alias with the `useExisting` option. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - var stylePattern = { otl: /(useExisting: \w*)/gm }; | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','providers-6b', '', stylePattern)(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #value-provider | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Value providers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Sometimes it's easier to provide a ready-made object rather than ask the injector to create it from a class. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block dart-diff-const-metadata-ctor | 
					
						
							|  |  |  |   //- N/A | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','silent-logger')(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Then we register a provider with the `useValue` option, | 
					
						
							|  |  |  |   which makes this object play the logger role. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - var stylePattern = { otl: /(useValue: \w*)/gm }; | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','providers-7', '', stylePattern)(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   See more `useValue` examples in the | 
					
						
							|  |  |  |   [Non-class dependencies](#non-class-dependencies) and | 
					
						
							|  |  |  |   [OpaqueToken](#opaquetoken) sections. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #factory-provider | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Factory providers | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Sometimes we need to create the dependent value dynamically, | 
					
						
							|  |  |  |   based on information we won't have until the last possible moment. | 
					
						
							|  |  |  |   Maybe the information changes repeatedly in the course of the browser session. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Suppose also that the injectable service has no independent access to the source of this information. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   This situation calls for a **factory provider**. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Let's illustrate by adding a new business requirement: | 
					
						
							|  |  |  |   the HeroService must hide *secret* heroes from normal users. | 
					
						
							|  |  |  |   Only authorized users should see secret heroes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Like the `EvenBetterLogger`, the `HeroService` needs a fact about the user. | 
					
						
							|  |  |  |   It needs to know if the user is authorized to see secret heroes. | 
					
						
							|  |  |  |   That authorization can change during the course of a single application session, | 
					
						
							|  |  |  |   as when we log in a different user. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Unlike `EvenBetterLogger`, we can't inject the `UserService` into the `HeroService`. | 
					
						
							|  |  |  |   The `HeroService` won't have direct access to the user information to decide | 
					
						
							|  |  |  |   who is authorized and who is not. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Why? We don't know either. Stuff like this happens. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Instead the `HeroService` constructor takes a boolean flag to control display of secret heroes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/heroes/hero.service.ts','internals', 'app/heroes/hero.service.ts (excerpt)')(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   We can inject the `Logger`, but we can't inject the  boolean `isAuthorized`. | 
					
						
							|  |  |  |   We'll have to take over the creation of new instances of this `HeroService` with a factory provider. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   A factory provider needs a factory function: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/heroes/hero.service.provider.ts','factory', 'app/heroes/hero.service.provider.ts (excerpt)')(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Although the `HeroService` has no access to the `UserService`, our factory function does. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We inject both the `Logger` and the `UserService` into the factory provider and let the injector pass them along to the factory function: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/heroes/hero.service.provider.ts','provider', 'app/heroes/hero.service.provider.ts (excerpt)')(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     The `useFactory` field tells Angular that the provider is a factory function | 
					
						
							|  |  |  |     whose implementation is the `heroServiceFactory`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     The `deps` property is #{_an} #{_array} of [provider tokens](#token). | 
					
						
							|  |  |  |     The `Logger` and `UserService` classes serve as tokens for their own class providers. | 
					
						
							|  |  |  |     The injector resolves these tokens and injects the corresponding services into the matching factory function parameters. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - var exportedvar = _docsFor == 'dart' ? 'constant' : 'exported variable' | 
					
						
							|  |  |  | - var variable = _docsFor == 'dart' ? 'constant' : 'variable' | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Notice that we captured the factory provider in #{_an} #{exportedvar}, `heroServiceProvider`. | 
					
						
							|  |  |  |   This extra step makes the factory provider reusable. | 
					
						
							|  |  |  |   We can register our `HeroService` with this #{variable} wherever we need it. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   In our sample, we need it only in the `HeroesComponent`, | 
					
						
							|  |  |  |   where it replaces the previous `HeroService` registration in the metadata `providers` #{_array}. | 
					
						
							|  |  |  |   Here we see the new and the old implementation side-by-side: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - var stylePattern = { otl: /(providers.*),$/gm }; | 
					
						
							|  |  |  | +makeTabs( | 
					
						
							|  |  |  |   `dependency-injection/ts/app/heroes/heroes.component.ts, | 
					
						
							|  |  |  |   dependency-injection/ts/app/heroes/heroes.component.1.ts`, | 
					
						
							|  |  |  |   ',full', | 
					
						
							|  |  |  |   `app/heroes/heroes.component (v3), | 
					
						
							|  |  |  |   app/heroes/heroes.component (v2)`, | 
					
						
							|  |  |  |   stylePattern) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-main-section#token | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## Dependency injection tokens | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   When we register a provider with an injector, we associate that provider with a dependency injection token. | 
					
						
							|  |  |  |   The injector maintains an internal *token-provider* map that it references when | 
					
						
							|  |  |  |   asked for a dependency. The token is the key to the map. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   In all previous examples, the dependency value has been a class *instance*, and | 
					
						
							|  |  |  |   the class *type* served as its own lookup key. | 
					
						
							|  |  |  |   Here we get a `HeroService` directly from the injector by supplying the `HeroService` type as the token: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/injector.component.ts','get-hero-service')(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   We have similar good fortune when we write a constructor that requires an injected class-based dependency. | 
					
						
							|  |  |  |   We define a constructor parameter with the `HeroService` class type, | 
					
						
							|  |  |  |   and Angular knows to inject the | 
					
						
							|  |  |  |   service associated with that `HeroService` class token: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/heroes/hero-list.component.ts', 'ctor-signature') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   This is especially convenient when we consider that most dependency values are provided by classes. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //- TODO: if function injection is useful explain or illustrate why. | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### Non-class dependencies | 
					
						
							|  |  |  | p | 
					
						
							|  |  |  |   | What if the dependency value isn't a class? Sometimes the thing we want to inject is a  | 
					
						
							|  |  |  |   block non-class-dep-eg | 
					
						
							|  |  |  |     span string, function, or object. | 
					
						
							|  |  |  | p | 
					
						
							|  |  |  |   | Applications often define configuration objects with lots of small facts  | 
					
						
							|  |  |  |   | (like the title of the application or the address of a web API endpoint) | 
					
						
							|  |  |  |   block config-obj-maps | 
					
						
							|  |  |  |     |  but these configuration objects aren't always instances of a class. | 
					
						
							|  |  |  |     | They can be object literals  | 
					
						
							|  |  |  |   |  such as this one: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/app.config.ts','config','app/app-config.ts (excerpt)')(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   We'd like to make this configuration object available for injection. | 
					
						
							|  |  |  |   We know we can register an object with a [value provider](#value-provider). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block what-should-we-use-as-token | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     But what should we use as the token? | 
					
						
							|  |  |  |     We don't have a class to serve as a token. | 
					
						
							|  |  |  |     There is no `AppConfig` class. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   .l-sub-section#interface | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       ### TypeScript interfaces aren't valid tokens | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       The `HERO_DI_CONFIG` constant has an interface, `AppConfig`. Unfortunately, we | 
					
						
							|  |  |  |       cannot use a TypeScript interface as a token: | 
					
						
							|  |  |  |     +makeExample('dependency-injection/ts/app/providers.component.ts','providers-9-interface')(format=".") | 
					
						
							|  |  |  |     +makeExample('dependency-injection/ts/app/providers.component.ts','provider-9-ctor-interface')(format=".") | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       That seems strange if we're used to dependency injection in strongly typed languages, where | 
					
						
							|  |  |  |       an interface is the preferred dependency lookup key. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |       It's not Angular's fault. An interface is a TypeScript design-time artifact. JavaScript doesn't have interfaces. | 
					
						
							|  |  |  |       The TypeScript interface disappears from the generated JavaScript. | 
					
						
							|  |  |  |       There is no interface type information left for Angular to find at runtime. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | //- FIXME simplify once APIs are defined for Dart. | 
					
						
							|  |  |  | - var opaquetoken = _docsFor == 'dart' ? '<b>OpaqueToken</b>' : '<a href="../api/core/index/OpaqueToken-class.html"><b>OpaqueToken</b></a>' | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ### OpaqueToken | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   One solution to choosing a provider token for non-class dependencies is | 
					
						
							|  |  |  |   to define and use an !{opaquetoken}. | 
					
						
							|  |  |  |   The definition looks like this: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/app.config.ts','token')(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   We register the dependency provider using the `OpaqueToken` object: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','providers-9')(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   Now we can inject the configuration object into any constructor that needs it, with | 
					
						
							|  |  |  |   the help of an `@Inject` #{_decorator}: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/app.component.2.ts','ctor')(format=".") | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - var configType = _docsFor == 'dart' ? '<code>Map</code>' : '<code>AppConfig</code>' | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Although the !{configType} interface plays no role in dependency injection, | 
					
						
							|  |  |  |     it supports typing of the configuration object within the class. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | block dart-map-alternative | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     Or we can provide and inject the configuration object in our top-level `AppComponent`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   +makeExcerpt('app/app.component.ts','providers') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #optional | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## Optional dependencies | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Our `HeroService` *requires* a `Logger`, but what if it could get by without | 
					
						
							|  |  |  |   a logger? | 
					
						
							|  |  |  |   We can tell Angular that the dependency is optional by annotating the  | 
					
						
							|  |  |  |   constructor argument with `@Optional()`: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +ifDocsFor('ts') | 
					
						
							|  |  |  |   +makeExample('dependency-injection/ts/app/providers.component.ts','import-optional', '') | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/providers.component.ts','provider-10-ctor', '')(format='.') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   When using `@Optional()`, our code must be prepared for a null value. If we | 
					
						
							|  |  |  |   don't register a logger somewhere up the line, the injector will set the | 
					
						
							|  |  |  |   value of `logger` to null. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-main-section | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## Summary | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We learned the basics of Angular dependency injection in this chapter. | 
					
						
							|  |  |  |   We can register various kinds of providers, | 
					
						
							|  |  |  |   and we know how to ask for an injected object (such as a service) by | 
					
						
							|  |  |  |   adding a parameter to a constructor. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Angular dependency injection is more capable than we've described. | 
					
						
							|  |  |  |   We can learn more about its advanced features, beginning with its support for | 
					
						
							|  |  |  |   nested injectors, in the | 
					
						
							|  |  |  |   [Hierarchical Dependency Injection](hierarchical-dependency-injection.html) chapter. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-main-section#explicit-injector | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   ## Appendix: Working with injectors directly | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   We rarely work directly with an injector, but | 
					
						
							|  |  |  |   here's an `InjectorComponent` that does. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +makeExample('dependency-injection/ts/app/injector.component.ts', 'injector', 'app/injector.component.ts') | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | :marked | 
					
						
							|  |  |  |   An `Injector` is itself an injectable service. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   In this example, Angular injects the component's own `Injector` into the component's constructor. | 
					
						
							|  |  |  |   The component then asks the injected injector for the services it wants. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   Note that the services themselves are not injected into the component. | 
					
						
							|  |  |  |   They are retrieved by calling `injector.get`. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   The `get` method throws an error if it can't resolve the requested service. | 
					
						
							|  |  |  |   We can call `get` with a second parameter (the value to return if the service is not found)  | 
					
						
							|  |  |  |   instead, which we do in one case | 
					
						
							|  |  |  |   to retrieve a service (`ROUS`) that isn't registered with this or any ancestor injector. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | .l-sub-section | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     The technique we just described is an example of the | 
					
						
							|  |  |  |     [service locator pattern](https://en.wikipedia.org/wiki/Service_locator_pattern). | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     We **avoid** this technique unless we genuinely need it. | 
					
						
							|  |  |  |     It encourages a careless grab-bag approach such as we see here. | 
					
						
							|  |  |  |     It's difficult to explain, understand, and test. | 
					
						
							|  |  |  |     We can't know by inspecting the constructor what this class requires or what it will do. | 
					
						
							|  |  |  |     It could acquire services from any ancestor component, not just its own. | 
					
						
							|  |  |  |     We're forced to spelunk the implementation to discover what it does. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Framework developers may take this approach when they | 
					
						
							|  |  |  |     must acquire services generically and dynamically. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | +ifDocsFor('ts') | 
					
						
							|  |  |  |   .l-main-section#one-class-per-file | 
					
						
							|  |  |  |   :marked | 
					
						
							|  |  |  |     ## Appendix: Why we recommend one class per file | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Having multiple classes in the same file is confusing and best avoided. | 
					
						
							|  |  |  |     Developers expect one class per file. Keep them happy. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     If we scorn this advice and, say, | 
					
						
							|  |  |  |     combine our `HeroService` class with the `HeroesComponent` in the same file, | 
					
						
							|  |  |  |     **define the component last!** | 
					
						
							|  |  |  |     If we define the component before the service, | 
					
						
							|  |  |  |     we'll get a runtime null reference error. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   .l-sub-section | 
					
						
							|  |  |  |     :marked | 
					
						
							|  |  |  |       We actually can define the component first with the help of the `forwardRef()` method as explained | 
					
						
							|  |  |  |       in this [blog post](http://blog.thoughtram.io/angular/2015/09/03/forward-references-in-angular-2.html). | 
					
						
							|  |  |  |       But why flirt with trouble? | 
					
						
							|  |  |  |       Avoid the problem altogether by defining components and services in separate files. |