` tags,
first without a value (yielding the default color) and then with an assigned color value.
+makeExample('cb-dependency-injection/ts/src/app/app.component.html','highlight','src/app/app.component.html (highlight)')(format='.')
:marked
The following image shows the effect of mousing over the `
` tag.
figure.image-display
img(src="/resources/images/cookbooks/dependency-injection/highlight.png" alt="Highlighted bios")
.l-main-section
:marked
## Define dependencies with providers
This section demonstrates how to write providers that deliver dependent services.
Get a service from a dependency injector by giving it a ***token***.
You usually let Angular handle this transaction by specifying a constructor parameter and its type.
The parameter type serves as the injector lookup *token*.
Angular passes this token to the injector and assigns the result to the parameter.
Here's a typical example:
+makeExample('cb-dependency-injection/ts/src/app/hero-bios.component.ts','ctor','src/app/hero-bios.component.ts (component constructor injection)')(format='.')
:marked
Angular asks the injector for the service associated with the `LoggerService`
and assigns the returned value to the `logger` parameter.
Where did the injector get that value?
It may already have that value in its internal container.
If it doesn't, it may be able to make one with the help of a ***provider***.
A *provider* is a recipe for delivering a service associated with a *token*.
.l-sub-section
:marked
If the injector doesn't have a provider for the requested *token*, it delegates the request
to its parent injector, where the process repeats until there are no more injectors.
If the search is futile, the injector throws an error—unless the request was [optional](#optional).
:marked
A new injector has no providers.
Angular initializes the injectors it creates with some providers it cares about.
You have to register your _own_ application providers manually,
usually in the `providers` array of the `Component` or `Directive` metadata:
+makeExample('cb-dependency-injection/ts/src/app/app.component.ts','providers','src/app/app.component.ts (providers)')
a#defining-providers
:marked
### Defining providers
The simple class provider is the most typical by far.
You mention the class in the `providers` array and you're done.
+makeExample('cb-dependency-injection/ts/src/app/hero-bios.component.ts','class-provider','src/app/hero-bios.component.ts (class provider)')(format='.')
:marked
It's that simple because the most common injected service is an instance of a class.
But not every dependency can be satisfied by creating a new instance of a class.
You need other ways to deliver dependency values and that means you need other ways to specify a provider.
The `HeroOfTheMonthComponent` example demonstrates many of the alternatives and why you need them.
figure.image-display
img(src="/resources/images/cookbooks/dependency-injection/hero-of-month.png" alt="Hero of the month" width="300px")
:marked
It's visually simple: a few properties and the output of a logger. The code behind it gives you plenty to think about.
+makeExample('cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts','hero-of-the-month','hero-of-the-month.component.ts')
.l-main-section
a(id='provide')
:marked
#### The *provide* object literal
The `provide` object literal takes a *token* and a *definition object*.
The *token* is usually a class but [it doesn't have to be](#tokens).
The *definition* object has one main property, `useValue`, that indicates how the provider
should create or return the provided value.
.l-main-section
a(id='usevalue')
:marked
#### useValue—the *value provider*
Set the `useValue` property to a ***fixed value*** that the provider can return as the dependency object.
Use this technique to provide *runtime configuration constants* such as website base addresses and feature flags.
You can use a *value provider* in a unit test to replace a production service with a fake or mock.
The `HeroOfTheMonthComponent` example has two *value providers*.
The first provides an instance of the `Hero` class;
the second specifies a literal string resource:
+makeExample('cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts','use-value')(format='.')
:marked
The `Hero` provider token is a class which makes sense because the value is a `Hero`
and the consumer of the injected hero would want the type information.
The `TITLE` provider token is *not a class*.
It's a special kind of provider lookup key called an [OpaqueToken](#opaquetoken).
You can use an `OpaqueToken` when the dependency is a simple value like a string, a number, or a function.
The value of a *value provider* must be defined *now*. You can't create the value later.
Obviously the title string literal is immediately available.
The `someHero` variable in this example was set earlier in the file:
+makeExample('cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts','some-hero')
:marked
The other providers create their values *lazily* when they're needed for injection.
.l-main-section
a(id='useclass')
:marked
#### useClass—the *class provider*
The `useClass` provider creates and returns new instance of the specified class.
Use this technique to ***substitute an alternative implementation*** for a common or default class.
The alternative could implement a different strategy, extend the default class,
or fake the behavior of the real class in a test case.
Here are two examples in the `HeroOfTheMonthComponent`:
+makeExample('cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts','use-class')(format='.')
:marked
The first provider is the *de-sugared*, expanded form of the most typical case in which the
class to be created (`HeroService`) is also the provider's injection token.
It's in this long form to de-mystify the preferred short form.
The second provider substitutes the `DateLoggerService` for the `LoggerService`.
The `LoggerService` is already registered at the `AppComponent` level.
When _this component_ requests the `LoggerService`, it receives the `DateLoggerService` instead.
.l-sub-section
:marked
This component and its tree of child components receive the `DateLoggerService` instance.
Components outside the tree continue to receive the original `LoggerService` instance.
:marked
The `DateLoggerService` inherits from `LoggerService`; it appends the current date/time to each message:
+makeExample('cb-dependency-injection/ts/src/app/date-logger.service.ts','date-logger-service','src/app/date-logger.service.ts')(format='.')
.l-main-section
a(id='useexisting')
:marked
#### _useExisting_—the *alias provider*
The `useExisting` provider maps one token to another.
In effect, the first token is an ***alias*** for the service associated with the second token,
creating ***two ways to access the same service object***.
+makeExample('cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts','use-existing')
:marked
Narrowing an API through an aliasing interface is _one_ important use case for this technique.
This example shows aliasing for that very purpose here.
Imagine that the `LoggerService` had a large API; it's actually only three methods and a property.
You'd want to shrink that API surface to just the two members exposed by the `MinimalLogger` [*class-interface*](#class-interface):
+makeExample('cb-dependency-injection/ts/src/app/date-logger.service.ts','minimal-logger','src/app/date-logger.service.ts (MinimalLogger)')(format='.')
:marked
The constructor's `logger` parameter is typed as `MinimalLogger` so only its two members are visible in TypeScript:
figure.image-display
img(src="/resources/images/cookbooks/dependency-injection/minimal-logger-intellisense.png" alt="MinimalLogger restricted API")
:marked
Angular actually sets the `logger` parameter to the injector's full version of the `LoggerService`
which happens to be the `DateLoggerService`. This is because of the override provider
registered previously via `useClass`.
The following image, which displays the logging date, confirms the point:
figure.image-display
img(src="/resources/images/cookbooks/dependency-injection/date-logger-entry.png" alt="DateLoggerService entry" width="300px")
.l-main-section
a(id='usefactory')
:marked
#### _useFactory_—the *factory provider*
The `useFactory` provider creates a dependency object by calling a factory function
as in this example.
+makeExample('cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts','use-factory')
:marked
Use this technique to ***create a dependency object***
with a factory function whose inputs are some ***combination of injected services and local state***.
The *dependency object* doesn't have to be a class instance. It could be anything.
In this example, the *dependency object* is a string of the names of the runners-up
to the "Hero of the Month" contest.
The local state is the number `2`, the number of runners-up this component should show.
It executes `runnersUpFactory` immediately with `2`.
The `runnersUpFactory` itself isn't the provider factory function.
The true provider factory function is the function that `runnersUpFactory` returns.
+makeExample('cb-dependency-injection/ts/src/app/runners-up.ts','factory-synopsis','runners-up.ts (excerpt)')(format='.')
:marked
That returned function takes a winning `Hero` and a `HeroService` as arguments.
Angular supplies these arguments from injected values identified by
the two *tokens* in the `deps` array.
The two `deps` values are *tokens* that the injector uses
to provide these factory function dependencies.
After some undisclosed work, the function returns the string of names
and Angular injects it into the `runnersUp` parameter of the `HeroOfTheMonthComponent`.
.l-sub-section
:marked
The function retrieves candidate heroes from the `HeroService`,
takes `2` of them to be the runners-up, and returns their concatenated names.
Look at the
for the full source code.
a(id="tokens")
.l-main-section
:marked
## Provider token alternatives: the *class-interface* and *OpaqueToken*
Angular dependency injection is easiest when the provider *token* is a class
that is also the type of the returned dependency object, or what you usually call the *service*.
But the token doesn't have to be a class and even when it is a class,
it doesn't have to be the same type as the returned object.
That's the subject of the next section.
:marked
### class-interface
The previous *Hero of the Month* example used the `MinimalLogger` class
as the token for a provider of a `LoggerService`.
+makeExample('cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts','use-existing')
:marked
The `MinimalLogger` is an abstract class.
+makeExample('cb-dependency-injection/ts/src/app/date-logger.service.ts','minimal-logger')(format='.')
:marked
You usually inherit from an abstract class.
But `LoggerService` doesn't inherit from `MinimalLogger`. *No class* inherits from it.
Instead, you use it like an interface.
Look again at the declaration for `DateLoggerService`:
+makeExample('cb-dependency-injection/ts/src/app/date-logger.service.ts','date-logger-service-signature')(format='.')
:marked
`DateLoggerService` inherits (extends) from `LoggerService`, not `MinimalLogger`.
The `DateLoggerService` *implements* `MinimalLogger` as if `MinimalLogger` were an *interface*.
When you use a class this way, it's called a ***class-interface***.
The key benefit of a *class-interface* is that you can get the strong-typing of an interface
and you can ***use it as a provider token*** in the same manner as a normal class.
A ***class-interface*** should define *only* the members that its consumers are allowed to call.
Such a narrowing interface helps decouple the concrete class from its consumers.
The `MinimalLogger` defines just two of the `LoggerClass` members.
.l-sub-section
:marked
#### Why *MinimalLogger* is a class and not an interface
You can't use an interface as a provider token because
interfaces are not JavaScript objects.
They exist only in the TypeScript design space.
They disappear after the code is transpiled to JavaScript.
A provider token must be a real JavaScript object of some kind:
such as a function, an object, a string, or a class.
Using a class as an interface gives you the characteristics of an interface in a JavaScript object.
To minimize memory cost, the class should have *no implementation*.
The `MinimalLogger` transpiles to this unoptimized, pre-minified JavaScript:
+makeExample('cb-dependency-injection/ts/src/app/date-logger.service.ts','minimal-logger-transpiled')(format='.')
:marked
It never grows larger no matter how many members you add *as long as they are typed but not implemented*.
a(id='opaque-token')
:marked
### _OpaqueToken_
Dependency objects can be simple values like dates, numbers and strings, or
shapeless objects like arrays and functions.
Such objects don't have application interfaces and therefore aren't well represented by a class.
They're better represented by a token that is both unique and symbolic,
a JavaScript object that has a friendly name but won't conflict with
another token that happens to have the same name.
The `OpaqueToken` has these characteristics.
You encountered them twice in the *Hero of the Month* example,
in the *title* value provider and in the *runnersUp* factory provider.
+makeExample('cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts','provide-opaque-token')(format='.')
:marked
You created the `TITLE` token like this:
+makeExample('cb-dependency-injection/ts/src/app/hero-of-the-month.component.ts','opaque-token')(format='.')
a(id="di-inheritance")
.l-main-section
:marked
## Inject into a derived class
Take care when writing a component that inherits from another component.
If the base component has injected dependencies,
you must re-provide and re-inject them in the derived class
and then pass them down to the base class through the constructor.
In this contrived example, `SortedHeroesComponent` inherits from `HeroesBaseComponent`
to display a *sorted* list of heroes.
figure.image-display
img(src="/resources/images/cookbooks/dependency-injection/sorted-heroes.png" alt="Sorted Heroes")
:marked
The `HeroesBaseComponent` could stand on its own.
It demands its own instance of the `HeroService` to get heroes
and displays them in the order they arrive from the database.
+makeExample('cb-dependency-injection/ts/src/app/sorted-heroes.component.ts','heroes-base','src/app/sorted-heroes.component.ts (HeroesBaseComponent)')
.l-sub-section
:marked
***Keep constructors simple.*** They should do little more than initialize variables.
This rule makes the component safe to construct under test without fear that it will do something dramatic like talk to the server.
That's why you call the `HeroService` from within the `ngOnInit` rather than the constructor.
:marked
Users want to see the heroes in alphabetical order.
Rather than modify the original component, sub-class it and create a
`SortedHeroesComponent` that sorts the heroes before presenting them.
The `SortedHeroesComponent` lets the base class fetch the heroes.
Unfortunately, Angular cannot inject the `HeroService` directly into the base class.
You must provide the `HeroService` again for *this* component,
then pass it down to the base class inside the constructor.
+makeExample('cb-dependency-injection/ts/src/app/sorted-heroes.component.ts','sorted-heroes','src/app/sorted-heroes.component.ts (SortedHeroesComponent)')
:marked
Now take note of the `afterGetHeroes()` method.
Your first instinct might have been to create an `ngOnInit` method in `SortedHeroesComponent` and do the sorting there.
But Angular calls the *derived* class's `ngOnInit` *before* calling the base class's `ngOnInit`
so you'd be sorting the heroes array *before they arrived*. That produces a nasty error.
Overriding the base class's `afterGetHeroes()` method solves the problem.
These complications argue for *avoiding component inheritance*.
a(id="find-parent")
.l-main-section
:marked
## Find a parent component by injection
Application components often need to share information.
More loosely coupled techniques such as data binding and service sharing
are preferable. But sometimes it makes sense for one component
to have a direct reference to another component
perhaps to access values or call methods on that component.
Obtaining a component reference is a bit tricky in Angular.
Although an Angular application is a tree of components,
there is no public API for inspecting and traversing that tree.
There is an API for acquiring a child reference.
Check out `Query`, `QueryList`, `ViewChildren`, and `ContentChildren`
in the [API Reference](../api/).
There is no public API for acquiring a parent reference.
But because every component instance is added to an injector's container,
you can use Angular dependency injection to reach a parent component.
This section describes some techniques for doing that.
### Find a parent component of known type
You use standard class injection to acquire a parent component whose type you know.
In the following example, the parent `AlexComponent` has several children including a `CathyComponent`:
a(id='alex')
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','alex-1','parent-finder.component.ts (AlexComponent v.1)')(format='.')
:marked
*Cathy* reports whether or not she has access to *Alex*
after injecting an `AlexComponent` into her constructor:
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','cathy','parent-finder.component.ts (CathyComponent)')(format='.')
:marked
Notice that even though the [@Optional](#optional) qualifier
is there for safety,
the
confirms that the `alex` parameter is set.
### Cannot find a parent by its base class
What if you *don't* know the concrete parent component class?
A re-usable component might be a child of multiple components.
Imagine a component for rendering breaking news about a financial instrument.
For business reasons, this news component makes frequent calls
directly into its parent instrument as changing market data streams by.
The app probably defines more than a dozen financial instrument components.
If you're lucky, they all implement the same base class
whose API your `NewsComponent` understands.
.l-sub-section
:marked
Looking for components that implement an interface would be better.
That's not possible because TypeScript interfaces disappear
from the transpiled JavaScript, which doesn't support interfaces.
There's no artifact to look for.
:marked
This isn't necessarily good design.
This example is examining *whether a component can
inject its parent via the parent's base class*.
The sample's `CraigComponent` explores this question. [Looking back](#alex),
you see that the `Alex` component *extends* (*inherits*) from a class named `Base`.
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','alex-class-signature','parent-finder.component.ts (Alex class signature)')(format='.')
:marked
The `CraigComponent` tries to inject `Base` into its `alex` constructor parameter and reports if it succeeded.
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','craig','parent-finder.component.ts (CraigComponent)')(format='.')
:marked
Unfortunately, this does not work.
The
confirms that the `alex` parameter is null.
*You cannot inject a parent by its base class.*
### Find a parent by its class-interface
You can find a parent component with a [class-interface](#class-interface).
The parent must cooperate by providing an *alias* to itself in the name of a *class-interface* token.
Recall that Angular always adds a component instance to its own injector;
that's why you could inject *Alex* into *Cathy* [earlier](#known-parent).
Write an [*alias provider*](#useexisting)—a `provide` object literal with a `useExisting`
definition—that creates an *alternative* way to inject the same component instance
and add that provider to the `providers` array of the `@Component` metadata for the `AlexComponent`:
a(id="alex-providers")
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','alex-providers','parent-finder.component.ts (AlexComponent providers)')(format='.')
:marked
[Parent](#parent-token) is the provider's *class-interface* token.
The [*forwardRef*](#forwardref) breaks the circular reference you just created by having the `AlexComponent` refer to itself.
*Carol*, the third of *Alex*'s child components, injects the parent into its `parent` parameter,
the same way you've done it before:
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','carol-class','parent-finder.component.ts (CarolComponent class)')(format='.')
:marked
Here's *Alex* and family in action:
figure.image-display
img(src="/resources/images/cookbooks/dependency-injection/alex.png" alt="Alex in action")
a(id="parent-tree")
:marked
### Find the parent in a tree of parents with _@SkipSelf()_
Imagine one branch of a component hierarchy: *Alice* -> *Barry* -> *Carol*.
Both *Alice* and *Barry* implement the `Parent` *class-interface*.
*Barry* is the problem. He needs to reach his parent, *Alice*, and also be a parent to *Carol*.
That means he must both *inject* the `Parent` *class-interface* to get *Alice* and
*provide* a `Parent` to satisfy *Carol*.
Here's *Barry*:
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','barry','parent-finder.component.ts (BarryComponent)')(format='.')
:marked
*Barry*'s `providers` array looks just like [*Alex*'s](#alex-providers).
If you're going to keep writing [*alias providers*](#useexisting) like this you should create a [helper function](#provideparent).
For now, focus on *Barry*'s constructor:
+makeTabs(
'cb-dependency-injection/ts/src/app/parent-finder.component.ts, cb-dependency-injection/ts/src/app/parent-finder.component.ts',
'barry-ctor, carol-ctor',
'Barry\'s constructor, Carol\'s constructor')(format='.')
:marked
:marked
It's identical to *Carol*'s constructor except for the additional `@SkipSelf` decorator.
`@SkipSelf` is essential for two reasons:
1. It tells the injector to start its search for a `Parent` dependency in a component *above* itself,
which *is* what parent means.
2. Angular throws a cyclic dependency error if you omit the `@SkipSelf` decorator.
`Cannot instantiate cyclic dependency! (BethComponent -> Parent -> BethComponent)`
Here's *Alice*, *Barry* and family in action:
figure.image-display
img(src="/resources/images/cookbooks/dependency-injection/alice.png" alt="Alice in action")
a(id="parent-token")
:marked
### The *Parent* class-interface
You [learned earlier](#class-interface) that a *class-interface* is an abstract class used as an interface rather than as a base class.
The example defines a `Parent` *class-interface*.
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','parent','parent-finder.component.ts (Parent class-interface)')(format='.')
:marked
The `Parent` *class-interface* defines a `name` property with a type declaration but *no implementation*.
The `name` property is the only member of a parent component that a child component can call.
Such a narrow interface helps decouple the child component class from its parent components.
A component that could serve as a parent *should* implement the *class-interface* as the `AliceComponent` does:
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','alice-class-signature','parent-finder.component.ts (AliceComponent class signature)')(format='.')
:marked
Doing so adds clarity to the code. But it's not technically necessary.
Although the `AlexComponent` has a `name` property, as required by its `Base` class,
its class signature doesn't mention `Parent`:
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','alex-class-signature','parent-finder.component.ts (AlexComponent class signature)')(format='.')
.l-sub-section
:marked
The `AlexComponent` *should* implement `Parent` as a matter of proper style.
It doesn't in this example *only* to demonstrate that the code will compile and run without the interface
a(id="provideparent")
:marked
### A _provideParent()_ helper function
Writing variations of the same parent *alias provider* gets old quickly,
especially this awful mouthful with a [*forwardRef*](#forwardref):
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','alex-providers')(format='.')
:marked
You can extract that logic into a helper function like this:
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','provide-the-parent')(format='.')
:marked
Now you can add a simpler, more meaningful parent provider to your components:
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','alice-providers')(format='.')
:marked
You can do better. The current version of the helper function can only alias the `Parent` *class-interface*.
The application might have a variety of parent types, each with its own *class-interface* token.
Here's a revised version that defaults to `parent` but also accepts an optional second parameter for a different parent *class-interface*.
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','provide-parent')(format='.')
:marked
And here's how you could use it with a different parent type:
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','beth-providers')(format='.')
a(id="forwardref")
.l-main-section
:marked
## Break circularities with a forward class reference (*forwardRef*)
The order of class declaration matters in TypeScript.
You can't refer directly to a class until it's been defined.
This isn't usually a problem, especially if you adhere to the recommended *one class per file* rule.
But sometimes circular references are unavoidable.
You're in a bind when class 'A' refers to class 'B' and 'B' refers to 'A'.
One of them has to be defined first.
The Angular `forwardRef()` function creates an *indirect* reference that Angular can resolve later.
The *Parent Finder* sample is full of circular class references that are impossible to break.
:marked
You face this dilemma when a class makes *a reference to itself*
as does the `AlexComponent` in its `providers` array.
The `providers` array is a property of the `@Component` decorator function which must
appear *above* the class definition.
Break the circularity with `forwardRef`:
+makeExample('cb-dependency-injection/ts/src/app/parent-finder.component.ts','alex-providers','parent-finder.component.ts (AlexComponent providers)')(format='.')
:marked