-
-
-
-Of course, this isn't a real service.
-If the app were actually getting data from a remote server, the API would have to be
-asynchronous, perhaps returning a [Promise](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise).
-You'd also have to rewrite the way components consume the service.
-This is important in general, but not in this example.
-
-
-
-
-
-
-A service is nothing more than a class in Angular.
-It remains nothing more than a class until you register it with an Angular injector.
-
-
-
+You'll learn much more about _providers_ [below](#providers).
+For now it is sufficient to know that they create services
+and must be registered with an injector.
-You do have to configure the injector by registering the **providers**
-that create the services the application requires.
-This guide explains what [providers](guide/dependency-injection#providers) are later.
+
+You can register a provider with any Angular decorator that supports the **`providers` array property**.
-You can either register a provider within an [NgModule](guide/ngmodule) or in application components.
-
-
-{@a register-providers-ngmodule}
-
-
-### Registering providers in an _NgModule_
-Here's the `AppModule` that registers two providers, `UserService` and an `APP_CONFIG` provider,
-in its `providers` array.
-
-
-
-
+
+{@a register-providers-ngmodule}
+
+### _@NgModule_ providers
+
+In the following excerpt, the root `AppModule` registers two providers in its `providers` array.
+
+
+
+
+The first entry registers the `UserService` class (_not shown_) under the `UserService` _injection token_.
+The second registers a value (`HERO_DI_CONFIG`) under the `APP_CONFIG` _injection token_.
+
+Thanks to these registrations, Angular can inject the `UserService` or the `HERO_DI_CONFIG` value
+into any class that it creates.
+
+
+
+You'll learn about _injection tokens_ and _provider_ syntax [below](#providers).
+
{@a ngmodule-vs-comp}
+### _@NgModule_ or _@Component_?
-### When to use _NgModule_ versus an application component
+Should you register a service with an Angular module or with a component?
+The two choices lead to differences in service _scope_ and service _lifetime_.
-On the one hand, a provider in an `NgModule` is registered in the root injector. That means that every provider
-registered within an `NgModule` will be accessible in the _entire application_.
-
-On the other hand, a provider registered in an application component is available only on
-that component and all its children.
-
-Here, the `APP_CONFIG` service needs to be available all across the application, so it's
-registered in the `AppModule` `@NgModule` `providers` array.
-But since the `HeroService` is only used within the *Heroes*
-feature area and nowhere else, it makes sense to register it in
-the `HeroesComponent`.
+**Angular module providers** (`@NgModule.providers`) are registered with the application's root injector.
+Angular can inject the corresponding services in any class it creates.
+Once created, a service instance lives for the life of the app and Angular injects this one service instance in every class that needs it.
+You're likely to inject the `UserService` in many places throughout the app
+and will want to inject the same service instance every time.
+Providing the `UserService` with an Angular module is a good choice.
+To be precise, Angular module providers are registered with the root injector
+_unless the module is_ [lazy loaded](guide/ngmodule#lazy-load).
+In this sample, all modules are _eagerly loaded_ when the application starts,
+so all module providers are registered with the app's root injector.
+
-Also see *"Should I add app-wide providers to the root `AppModule` or
-the root `AppComponent`?"* in the [NgModule FAQ](guide/ngmodule-faq#q-root-component-or-module).
+
+**A component's providers** (`@Component.providers`) are registered with each component instance's own injector.
+
+Angular can only inject the corresponding services in that component instance or one of its descendant component instances.
+Angular cannot inject the same service instance anywhere else.
+
+Note that a component-provided service may have a limited lifetime. Each new instance of the component gets its own instance of the service
+and, when the component instance is destroyed, so is that service instance.
+
+In this sample app, the `HeroComponent` is created when the application starts
+and is never destroyed so the `HeroService` created for the `HeroComponent` also live for the life of the app.
+
+If you want to restrict `HeroService` access to the `HeroComponent` and its nested `HeroListComponent`,
+providing the `HeroService` in the `HeroComponent` may be a good choice.
+
+
+
+The scope and lifetime of component-provided services is a consequence of [the way Angular creates component instances](#component-child-injectors).
+## Inject a service
+The `HeroListComponent` should get heroes from the `HeroService`.
-{@a prep-for-injection}
+The component shouldn't create the `HeroService` with `new`.
+It should ask for the `HeroService` to be injected.
+You can tell Angular to inject a dependency in the component's constructor by specifying a **constructor parameter with the dependency type**.
+Here's the `HeroListComponent` constructor, asking for the `HeroService` to be injected.
-### 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 discussed earlier](guide/dependency-injection#ctor-injection).
-It's a small change:
+
+
+Of course, the `HeroListComponent` should do something with the injected `HeroService`.
+Here's the revised component, making use of the injected service, side-by-side with the previous version for comparison.
-
-
-
+
-
-
+
-
-
-
-
-
-
-
-#### Focus on the constructor
-
-Adding a parameter to the constructor isn't all that's happening here.
-
-
-
-
-
-
-
-
-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`.
-
-
-
-
-
-
-{@a di-metadata}
-
-
-### Implicit injector creation
-
-You saw how to use an injector to create a new
-`Car` earlier in this guide.
-You _could_ create such an injector
-explicitly:
-
-
-
-
-
-
-
-
-You won't find code like that in the Tour of Heroes or any of the other
-documentation samples.
-You *could* write code that [explicitly creates an injector](guide/dependency-injection#explicit-injector) if you *had* to,
-but it's not always the best choice.
-Angular takes care of creating and calling injectors
-when it creates components for you—whether through HTML markup, as in ``,
-or after navigating to a component with the [router](guide/router).
-If you let Angular do its job, you'll enjoy the benefits of automated dependency injection.
-
+Notice that the `HeroListComponent` doesn't know where the `HeroService` comes from.
+_You_ know that it comes from the parent `HeroesComponent`.
+But if you decided instead to provide the `HeroService` in the `AppModule`,
+the `HeroListComponent` wouldn't change at all.
+The _only thing that matters_ is that the `HeroService` is provided in some parent injector.
{@a singleton-services}
+## Singleton services
-### Singleton services
+Services are singletons _within the scope of an injector_.
+There is at most one instance of a service in a given injector.
-Dependencies are singletons within the scope of an injector.
-In this guide's example, a single `HeroService` instance is shared among the
-`HeroesComponent` and its `HeroListComponent` children.
+There is only one root injector and the `UserService` is registered with that injector.
+Therefore, there can be just one `UserService` instance in the entire app
+and every class that injects `UserService` get this service instance.
-However, Angular DI is a hierarchical injection
-system, which means that nested injectors can create their own service instances.
-For more information, see [Hierarchical Injectors](guide/hierarchical-dependency-injection).
+However, Angular DI is a
+[hierarchical injection system](guide/hierarchical-dependency-injection),
+which means that nested injectors can create their own service instances.
+Angular creates nested injectors all the time.
+{@a component-child-injectors}
+
+## Component child injectors
+
+For example, when Angular creates a new instance of a component that has `@Component.providers`,
+it also creates a new _child injector_ for that instance.
+
+Component injectors are independent of each other and
+each of them creates its own instances of the component-provided services.
+
+When Angular destroys one of these component instance, it also destroys the
+component's injector and that injector's service instances.
+
+Thanks to [injector inheritance](guide/hierarchical-dependency-injection),
+you can still inject application-wide services into these components.
+A component's injector is a child of its parent component's injector,
+and a descendent of its parent's parent's injector, and so on all the way back to the application's _root_ injector.
+Angular can inject a service provided by any injector in that lineage.
+
+For example, Angular could inject a `HeroListComponent`
+with both the `HeroService` provided in `HeroComponent`
+and the `UserService` provided in `AppModule`.
{@a testing-the-component}
-
-### Testing the component
+## Testing the component
Earlier you saw that designing a class for dependency injection makes the class easier to test.
Listing dependencies as constructor parameters may be all you need to test application parts effectively.
@@ -512,234 +268,132 @@ Listing dependencies as constructor parameters may be all you need to test appli
For example, you can create a new `HeroListComponent` with a mock service that you can manipulate
under test:
-
-
-
-
-
-
-Learn more in [Testing](guide/testing).
-
+Learn more in the [Testing](guide/testing) guide.
-
-
{@a service-needs-service}
-
-### When the service needs a service
+## When the service needs a service
The `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?
You'd apply the same *constructor injection* pattern,
adding a constructor that takes a `Logger` parameter.
-Here is the revision compared to the original.
-
+Here is the revised `HeroService` that injects the `Logger`, side-by-side with the previous service for comparison.
-
-
-
-
-The constructor now asks for an injected instance of a `Logger` and stores it in a private property called `logger`.
-You call that property within the `getHeroes()` method when anyone asks for heroes.
-
-
-{@a injectable}
-
-
-### Why _@Injectable()_?
-
-**[@Injectable()](api/core/Injectable)** marks a class as available to an
-injector for instantiation. Generally speaking, an injector reports an
-error when trying to instantiate a class that is not marked as
-`@Injectable()`.
-
-
-
-
-
-
-As it happens, you could have omitted `@Injectable()` from the first
-version of `HeroService` because it had no injected parameters.
-But you must have it now that the service has an injected dependency.
-You need it because Angular requires constructor parameter metadata
-in order to inject a `Logger`.
-
-
-
-
-
-
-
-
-
-
-
- Suggestion: add @Injectable() to every service class
-
-
-
-
-Consider adding `@Injectable()` to every service class, even those that don't have dependencies
-and, therefore, do not technically require it. Here's why:
-
-
-
-
- -
- Future proofing: No need to remember
@Injectable()
when you add a dependency later.
-
-
- -
- Consistency: All services follow the same rules, and you don't have to wonder why a decorator is missing.
-
-
-
-
-
-
-
-
-
-
-Injectors are also responsible for instantiating components
-like `HeroesComponent`. So why doesn't `HeroesComponent` have
-`@Injectable()`?
-
-You *can* add it if you really want to. It isn't necessary because the
-`HeroesComponent` is already marked with `@Component`, and this
-decorator class (like `@Directive` and `@Pipe`, which you learn about later)
-is a subtype of [@Injectable()](api/core/Injectable). It is in
-fact `@Injectable()` decorators that
-identify a class as a target for instantiation by an injector.
-
-
-
-
-
-
-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
-[@Injectable()](api/core/Injectable) decorator
-to make the intent clear.
-
-
-
-
-
-
-
-
-
-
-
- Always include the parentheses
-
-
-
-
-Always write `@Injectable()`, not just `@Injectable`.
-The application will fail mysteriously if you forget the parentheses.
-
-
-
+The constructor asks for an injected instance of a `Logger` and stores it in a private field called `logger`.
+The `getHeroes()` method logs a message when asked to fetch heroes.
{@a logger-service}
-## Creating and registering a logger service
-
-Inject a logger into `HeroService` in two steps:
-
-1. Create the logger service.
-1. Register it with the application.
-
-The logger service is quite simple:
+#### The dependent _Logger_ service
+The sample app's `Logger` service is quite simple:
+
+If the app didn't provide this `Logger`,
+Angular would throw an exception when it looked for a `Logger` to inject
+into the `HeroService`.
+
+
+ ERROR Error: No provider for Logger!
+
+
+Because a singleton logger service is useful everywhere,
+it's provided in the root `AppModule`.
+
+
-You're likely to need the same logger service everywhere in your application,
-so put it in the project's `app` folder and
-register it in the `providers` array of the application module, `AppModule`.
+{@a injectable}
+## _@Injectable()_
-
+The **[@Injectable()](api/core/Injectable)** decorator identifies a service class
+that _might_ require injected dependencies.
-
+The `HeroService` must be annotated with `@Injectable()` because it requires an injected `Logger`.
+
+Always write `@Injectable()` with parentheses, not just `@Injectable`.
-If you forget to register the logger, Angular throws an exception when it first looks for the logger:
+
-
- EXCEPTION: No provider for Logger! (HeroListComponent -> HeroService -> Logger)
+When Angular creates a class whose constructor has parameters,
+it looks for type and injection metadata about those parameters
+so that it can inject the right service.
-
+If Angular can't find that parameter information, it throws an error.
+Angular can only find the parameter information _if the class has a decorator of some kind_.
+While _any_ decorator will do,
+the `@Injectable()` decorator is the standard decorator for service classes.
+
+The decorator requirement is imposed by TypeScript.
-That's Angular telling you 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`.
+TypeScript normally discards parameter type information when it _transpiles_ the code to JavaScript.
+It preserves this information if the class has a decorator
+and the `emitDecoratorMetadata` compiler option is set `true`
+in TypeScript's `tsconfig.json` configuration file, .
-The chain of creations started with the `Logger` provider. *Providers* are the subject of the next section.
+The CLI configures `tsconfig.json` with `emitDecoratorMetadata: true`
+It's your job to put `@Injectable()` on your service classes.
+
+
+
+The `Logger` service is annotated with `@Injectable()` decorator too,
+although it has no constructor and no dependencies.
+
+In fact, _every_ Angular service class in this app is annotated with the `@Injectable()` decorator, whether or not it has a constructor and dependencies.
+`@Injectable()` is a required coding style for services.
{@a providers}
-## Injector providers
+## Providers
-A provider *provides* the concrete, runtime version of a dependency value.
+A service 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.
+that the injector injects into components, directives, pipes, and other services.
-You must register a service *provider* with the injector, or it won't know how to create the service.
+You must register a service *provider* with an injector, or it won't know how to create the service.
-Earlier you registered the `Logger` service in the `providers` array of the metadata for the `AppModule` like this:
-
-
-
-
-
+The next few sections explain the many ways you can specify a provider.
+Almost all of the accompanying code snippets are extracts from the sample app's `providers.component.ts` file.
+### The class as its own provider
There are many ways to *provide* something that looks and behaves like a `Logger`.
The `Logger` class itself is an obvious and natural provider.
+
+
+
+
But it's not the only way.
You can configure the injector with alternative providers that can deliver an object that behaves like a `Logger`.
@@ -749,48 +403,29 @@ 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`.
+{@a provide}
-
+### The _provide_ object literal
-
-
-
-
-### The *Provider* class and _provide_ object literal
-
-
-You wrote the `providers` array like this:
-
-
-
+Here's the class-provider syntax again.
+
-
-
This is actually a shorthand expression for a provider registration
using a _provider_ object literal with two properties:
-
-
-
+
-
-
-The first is the [token](guide/dependency-injection#token) that serves as the key for both locating a dependency value
+The `provide` property holds the [token](guide/dependency-injection#token) that serves as the key for both locating a dependency value
and registering the provider.
-The second is a provider definition object,
+The second property is always a provider definition object,
which you can think of as a *recipe* for creating the dependency value.
There are many ways to create dependency values just as there are many ways to write a recipe.
-
-
-
-
-
-
+{@a class-provider}
### Alternative class providers
@@ -798,40 +433,27 @@ Occasionally you'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`.
-
-
-
+
-
-
{@a class-provider-dependencies}
-
### 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 is also injected at the application level.
-
-
-
+
-
-
Configure it like `BetterLogger`.
-
-
-
+
-
-
{@a aliased-class-providers}
-
### Aliased class providers
Suppose an old component depends upon an `OldLogger` class.
@@ -848,57 +470,34 @@ The `OldLogger` should be an alias for `NewLogger`.
You certainly do not want two different `NewLogger` instances in your app.
Unfortunately, that's what you get if you try to alias `OldLogger` to `NewLogger` with `useClass`.
-
-
-
+
-
-
The solution: alias with the `useExisting` option.
-
-
-
-
{@a value-provider}
-
### Value providers
-
Sometimes it's easier to provide a ready-made object rather than ask the injector to create it from a class.
-
-
-
+
-
-
Then you register a provider with the `useValue` option,
which makes this object play the logger role.
-
-
-
-
See more `useValue` examples in the
[Non-class dependencies](guide/dependency-injection#non-class-dependencies) and
[InjectionToken](guide/dependency-injection#injection-token) sections.
-
-
-
-
-
-
+{@a factory-provider}
### Factory providers
@@ -923,44 +522,29 @@ Unlike `EvenBetterLogger`, you can't inject the `UserService` into the `HeroServ
The `HeroService` won't have direct access to the user information to decide
who is authorized and who is not.
-
Instead, the `HeroService` constructor takes a boolean flag to control display of secret heroes.
-
-
-
-
You can inject the `Logger`, but you can't inject the boolean `isAuthorized`.
You'll have to take over the creation of new instances of this `HeroService` with a factory provider.
A factory provider needs a factory function:
-
-
-
-
Although the `HeroService` has no access to the `UserService`, the factory function does.
You inject both the `Logger` and the `UserService` into the factory provider
and let the injector pass them along to the factory function:
-
-
-
-
-
-
The `useFactory` field tells Angular that the provider is a factory function
whose implementation is the `heroServiceFactory`.
@@ -968,11 +552,8 @@ The `deps` property is an array of [provider tokens](guide/dependency-injection#
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.
-
-
-
Notice that you captured the factory provider in an exported variable, `heroServiceProvider`.
This extra step makes the factory provider reusable.
You can register the `HeroService` with this variable wherever you need it.
@@ -981,20 +562,16 @@ In this sample, you need it only in the `HeroesComponent`,
where it replaces the previous `HeroService` registration in the metadata `providers` array.
Here you see the new and the old implementation side-by-side:
-
-
-
-
+
-
{@a token}
## Dependency injection tokens
@@ -1007,85 +584,54 @@ In all previous examples, the dependency value has been a class *instance*, and
the class *type* served as its own lookup key.
Here you get a `HeroService` directly from the injector by supplying the `HeroService` type as the token:
-
-
-
-
You have similar good fortune when you write a constructor that requires an injected class-based dependency.
When you define a constructor parameter with the `HeroService` class type,
Angular knows to inject the
service associated with that `HeroService` class token:
-
-
-
-
This is especially convenient when you consider that most dependency values are provided by classes.
-
{@a non-class-dependencies}
-
### Non-class dependencies
-
- What if the dependency value isn't a class? Sometimes the thing you want to inject is a
- string, function, or object.
-
+What if the dependency value isn't a class? Sometimes the thing you want to inject is a
+string, function, or object.
+Applications often define configuration objects with lots of small facts
+(like the title of the application or the address of a web API endpoint)
+but these configuration objects aren't always instances of a class.
+They can be object literals such as this one:
-
-
- Applications often define configuration objects with lots of small facts
- (like the title of the application or the address of a web API endpoint)
- but these configuration objects aren't always instances of a class.
- They can be object literals such as this one:
-
-
-
-
-
-
+
-
-
What if you'd like to make this configuration object available for injection?
You know you can register an object with a [value provider](guide/dependency-injection#value-provider).
-
But what should you use as the token?
You don't have a class to serve as a token.
There is no `AppConfig` class.
-
-
-
### TypeScript interfaces aren't valid tokens
-The `HERO_DI_CONFIG` constant has an interface, `AppConfig`. Unfortunately, you
-cannot use a TypeScript interface as a token:
-
-
+The `HERO_DI_CONFIG` constant conforms to the `AppConfig` interface.
+Unfortunately, you cannot use a TypeScript interface as a token:
+
-
-
-
-
+
-
-
That seems strange if you're used to dependency injection in strongly typed languages, where
an interface is the preferred dependency lookup key.
@@ -1093,70 +639,45 @@ It's not Angular's doing. An interface is a TypeScript design-time artifact. Jav
The TypeScript interface disappears from the generated JavaScript.
There is no interface type information left for Angular to find at runtime.
-
-
-
{@a injection-token}
-
### _InjectionToken_
One solution to choosing a provider token for non-class dependencies is
to define and use an [*InjectionToken*](api/core/InjectionToken).
The definition of such a token looks like this:
-
-
-
-
The type parameter, while optional, conveys the dependency's type to developers and tooling.
The token description is another developer aid.
Register the dependency provider using the `InjectionToken` object:
-
-
-
+
-
-
Now you can inject the configuration object into any constructor that needs it, with
the help of an `@Inject` decorator:
-
-
-
-
-
-
Although the `AppConfig` interface plays no role in dependency injection,
it supports typing of the configuration object within the class.
-
-
-
Alternatively, you can provide and inject the configuration object in an ngModule like `AppModule`.
-
-
-
-
-
-
+
+{@a optional}
## Optional dependencies
@@ -1165,25 +686,16 @@ a `logger`?
You can tell Angular that the dependency is optional by annotating the
constructor argument with `@Optional()`:
-
-
-
-
-
-
-
When using `@Optional()`, your code must be prepared for a null value. If you
don't register a `logger` somewhere up the line, the injector will set the
value of `logger` to null.
-
-
## Summary
You learned the basics of Angular dependency injection in this page.
@@ -1203,13 +715,9 @@ nested injectors, in
Developers rarely work directly with an injector, but
here's an `InjectorComponent` that does.
-
-
-
-
An `Injector` is itself an injectable service.
In this example, Angular injects the component's own `Injector` into the component's constructor.
@@ -1245,7 +753,7 @@ must acquire services generically and dynamically.
{@a one-class-per-file}
-## Appendix: Why have one class per file
+## Appendix: 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.
@@ -1259,12 +767,10 @@ you'll get a runtime null reference error.
-
-
You 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.
+
+But it's best to avoid the problem altogether by defining components and services in separate files.
diff --git a/aio/content/navigation.json b/aio/content/navigation.json
index df7203a0e4..137de17ce5 100644
--- a/aio/content/navigation.json
+++ b/aio/content/navigation.json
@@ -243,10 +243,15 @@
"title": "Dependency Injection",
"tooltip": "Dependency Injection: creating and injecting services",
"children": [
+ {
+ "url": "guide/dependency-injection-pattern",
+ "title": "The Dependency Injection pattern",
+ "tooltip": "Learn about the dependency injection pattern behind the Angular DI system."
+ },
{
"url": "guide/dependency-injection",
- "title": "Dependency Injection",
- "tooltip": "Angular's dependency injection system creates and delivers dependent services \"just-in-time\"."
+ "title": "Angular Dependency Injection",
+ "tooltip": "Angular's dependency injection system creates and delivers dependent services to Angular-created classes."
},
{
"url": "guide/hierarchical-dependency-injection",