` tags,
first without a value (yielding the default color) and then with an assigned color value.
下面的代码把指令`myHighlight`属性使用到两个`
`标签里,一个没有赋值,一个赋值了颜色。
+makeExample('cb-dependency-injection/ts/app/app.component.html','highlight','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")
:marked
.l-main-section
:marked
## Define dependencies with providers
## 使用providers来定义依赖
In this section we learn to write providers that deliver dependent services.
在这个部分,我们学习如何编写providers来提供依赖服务。
### Background
### 背景知识
We get a service from a dependency injector by giving it a ***token***.
我们从一个依赖注入器,通过给他一个***令牌(token)***来获取一个服务。
We usually let Angular handle this transaction for us 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:
我们通常在构造函数的参数里面,制定一个参数给对应的类型,让Angular来处理该过程(依赖注入)。该参数类型是我们注入器寻找的*令牌*。
Angular把该令牌传递给注入器,然后把结果赋给参数。下例是一个典型的例子:
+makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','ctor','app/hero-bios.component.ts (component constructor injection)')(format='.')
:marked
Angular asks the injector for the service associated with the `LoggerService` and
and assigns the returned value to the `logger` parameter.
Angular找注入器要`LoggerService`对应的服务,并将返回的值赋值给`logger`参数。
Where did the injector get that value?
It may already have that value in its internal container.
It 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*.
注入器在哪儿得到的返回值?
它可能在自己内部容器里已经有该值了。
如果它没有,他可能能在***provider***的帮助下新建一个。
一个*provider*是一个通过指令派送对应的服务方法。
.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).
如果注入器对请求的令牌没有一个对应的provider,它便将这个请求交给它父级的注入器,这个过程反复从夫,知道没有更多注入器位置。
如果搜索无用,注入器便抛出一个错误...除非这个请求是[optional](#optional)。
Let's return our attention to providers themselves.
让我们把注意力转回到providers。
:marked
A new injector has no providers.
一个新的注入器没有providers。
Angular initializes the injectors it creates with some providers it cares about.
We have to register our _own_ application providers manually,
usually in the `providers` array of the `Component` or `Directive` metadata:
Angular初始化一些他自己建立和需要的注入器,附带一些providers。我们必须要亲自手动注册属于_自己_的providers,通常在`组件`或者`指令`的元数据里面的`providers`数组(里面注册)。
+makeExample('cb-dependency-injection/ts/app/app.component.ts','providers','app/app.component.ts (providers)')
:marked
### Defining providers
### 定义providers
The simple class provider is the most typical by far.
We mention the class in the `providers` array and we're done.
目前一个简单的类provider是最典型的例子。
我们在`providers`的数值里面提到该类就行了。
+makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','class-provider','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.
We need other ways to deliver dependency values and that means we need other ways to specify a provider.
这就是那么简单,因为最常见的被注入的服务是一个类的实例。但是,不是所有的依赖能在能建立一个类的新实例就够了的。我们需要其他的提交依赖值得方法,也就是说我们需要其他方法来制定一个provider。
The `HeroOfTheMonthComponent` example demonstrates many of the alternatives and why we need them.
`HeroOfTheMonthComponent`例子示范了一些备择方案,揭示了为什么我们需要他们。
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 us plenty to talk about.
它看起来很简单:一些属性和一个日志output。但是后面的代码给我们很多议论点。
+makeExample('cb-dependency-injection/ts/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* function
#### *provide*函数
The imported Angular `provide` function creates an instance of
the Angular [Provider](../api/core/Provider-class.html) class.
被导入的Angular `provide`函数新建一个Angular [Provider](../api/core/Provider-class.html)类的实例。
The `provide` function takes a *token* and a *definition object*.
The *token* is usually a class but [it doesn't have to be](#tokens).
该`provide`函数需要一个*令牌*和一个*定义对象*。该*令牌*通常是一个类,但是[他不是一定是](#tokens)
The *definition* object has one main property, (e.g. `useValue`) that indicates how the provider
should create or return the provided value.
该*定义*项目有一个主要属性,(即为`userValue`)来标识该provider应该怎么新建和返回被提供的结果。
.l-main-section
a(id='usevalue')
:marked
#### useValue - the *value provider*
#### useValue - *值provider*
Set the `useValue` property to a ***fixed value*** that the provider can return as the dependency object.
把一个***固定的值**,也就是该provider可以当作依赖对象返回的值,赋给`userValue`属性。
Use this technique to provide *runtime configuration constants* such as web-site base addresses and feature flags.
We often use a *value provider* in a unit test to replace a production service with a fake or mock.
使用该技巧来提供*运行时间设置常量*,比如网站的基础地址和功能标志等。我们通常在单元测试中使用一个*value provider*,用一个假的或模仿的(服务)来取代一个成品服务。
The `HeroOfTheMonthComponent` example has two *value providers*.
The first provides an instance of the `Hero` class;
the second specifies a literal string resource:
`HeroOfTheMonthComponent`例子有两个*value providers*。
第一个提供了一个`Hero`类的实例;第二个指定了一个文字字符串资源:
+makeExample('cb-dependency-injection/ts/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.
该`Hero`provider令牌是一个类,这很合理,因为提供的结果是一个`Hero`,而且使用这个被注入英雄的组件也想要知道这个类型信息。
The `TITLE` provider token is *not a class*.
It's a special kind of provider lookup key called an [OpaqueToken](#opaquetoken).
We often use an `OpaqueToken` when the dependency is a simple value like a string, a number, or a function.
`TITLE` provider令牌*不是一个类*。它是一个特别类型的provider查询键,名叫[OpaqueToken](#opaquetoken).
The value of a *value provider* must be defined *now*. We 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:
一个*value provider*的值必须要*立刻*定义。我们不能过后定义它的值。很显然,该标题字符串立刻可用。
该例中的`someHero`变量是于早先,在下面的文件里面定义的:
+makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','some-hero')
:marked
The other providers create their values *lazily* when they're needed for injection.
其他providers只在注入需要他们的时候才创建他们值 - *延迟加载*
.l-main-section
a(id='useclass')
:marked
#### useClass - the *class provider*
#### useClass - *类provider*
The `useClass` provider creates and returns new instance of the specified class.
`userClass` provider创建并返回一个特定类的新实例。
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.
使用此项技术来为公共或默认类***提供候选实现***。该候选方法能实现一个不同的策略,拓展默认类,或者在测试的时候假冒正真类的行为。
We see two examples in the `HeroOfTheMonthComponent`:
请看下面`HeroOfTheMonthComponent`里的两个例子:
+makeExample('cb-dependency-injection/ts/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.
We wrote it in this long form to de-mystify the preferred short form.
第一个provider是*无语法糖的*,是从典型的情况扩展的,一般被新建的类(`HeroService`)同时也是该provider的注入令牌。
我们使用长的形式来编写它来解释首选的短形式。
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.
第二个provider使用`DateLoggerService`来满足`LoggerService`。该`LoggerService`在`AppComponent`级别已经被注册。当_这个组件_要求`LoggerService`的时候,取而代之,它得到的是`DateLoggerService`服务。
.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.
这个组件和它的子级组件树得到`DateLoggerService`实例。在这些组件之外的组件树得到的还是`LoggerService`实例。
:marked
The `DateLoggerService` inherits from `LoggerService`; it appends the current date/time to each message:
`DateLoggerService`从`LoggerService`继承;它把当前的日期/时间附加到每条信息上。
+makeExample('cb-dependency-injection/ts/app/date-logger.service.ts','date-logger-service','app/date-logger.service.ts')(format='.')
.l-main-section
a(id='useexisting')
:marked
#### useExisting - the *alias provider*
#### useExisting - *别名provider*
The `useExisting` provider maps one token to another.
In effect, the first token is an ***alias*** for the service associated with second token,
creating ***two ways to access the same service object***.
使用`useExisting` provider来把一个令牌映射到另一个。实际上,第一个令牌是第二个令牌所对应的服务的一个***别名***,构成***对一个服务对象的两种访问方法***。
+makeExample('cb-dependency-injection/ts/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.
We're aliasing for that very purpose here.
Imagine that the `LoggerService` had a large API (it's actually only three methods and a property).
We want to shrink that API surface to just the two members exposed by the `MinimalLogger` [*class-interface*](#class-interface):
通过使用别名接口,把一个API变窄,是_一个_很重要的该技术的使用例子。我们在这里就是为了这个目的使用了别名。
想象一下如果`LoggerService`有个很大的API(它其实只有三个方法,一个属性),我们通过使用`MinimalLogger`[*类-接口*](#class-interface)别名要把这个API界面缩小到只暴露两个成员:
+makeExample('cb-dependency-injection/ts/app/date-logger.service.ts','minimal-logger','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:
构造函数的`logger`参数是一个`MinimalLogger`类型,所有它只有两个成员在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` thanks to the override provider registered previously via `useClass`.
The following image, which displays the logging date, confirms the point:
Angular实际上设置`logger`参数给注入器里的`LoggerService`的完整版本,该完整版本被`DateLoggerService`所取代,多谢在之前provder注册里使用`useClass`。
在下面的图片中,显示了日志日期,确认了这点:
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*
#### useFactory - *factory provider*
The `useFactory` provider creates a dependency object by calling a factory function
as seen in this example.
`useFactory` provider通过调用一个在下例看到的factory函数来新建一个依赖对象。
+makeExample('cb-dependency-injection/ts/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***.
使用这个技巧,利用一个包含了一些***依赖服务和本地状态***的输入的factory函数,来***建立一个依赖对象***。
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.
We execute `runnersUpFactory` immediately with `2`.
本地状态是数字`2`,该组件应该显示的亚军的个数。我们立刻用`2`来执行`runnersUpFactory`。
The `runnersUpFactory` itself isn't the provider factory function.
The true provider factory function is the function that `runnersUpFactory` returns.
`runnersUpFactory`自己provider factory函数。真正的provider factory函数是一个`runnersUpFactory`返回的函数。
+makeExample('cb-dependency-injection/ts/app/runners-up.ts','factory-synopsis','runners-up.ts (excerpt)')(format='.')
:marked
That returned function takes a winning `Hero` and a `HeroService` as arguments.
这个返回的函数需要一个`Hero`和一个`HeroService`参数。
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.
Angular通过注入值提供这些参数,这些值是从`deps`数组中使用两个*令牌*来提取的。这两个`deps`值是注入器使用*令牌*来提供的factory函数依赖。
After some undisclosed work, the function returns the string of names
and Angular injects it into the `runnersUp` parameter of the `HeroOfTheMonthComponent`.
一些没有公开的工作后,这个函数返回名字字符串,Angular将其注入到`HeroOfTheMonthComponent`组件的`runnersUp`参数里面。
.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 [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)
for the full source code.
该函数从`HeroService`获取英雄参赛者,从中取`2`个作为亚军,并把他们的名字合并起来。亲到[在线例子](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)看全部原代码。
a(id="tokens")
.l-main-section
:marked
## Provider token alternatives: the *class-interface* and *OpaqueToken*
## 可选Provider令牌:**类-接口*和*OpaqueToken*
Angular dependency injection is easiest when the provider *token* is a class
that is also the type of the returned dependency object (what we usually call the *service*).
Angular依赖注入在*令牌*为类,并且该类同时也是返回依赖的对象的时候最为容易(我们通常叫*服务*)。
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 our next section.
但是令牌不一定非要是类,就算它是一个类,它也不一定非要是返回对象相同类型的类。这是我们下一节的课题。
### class-interface
### 类-接口
In the previous *Hero of the Month* example, we used the `MinimalLogger` class
as the token for a provider of a `LoggerService`.
在前面的*每月英雄*的例子中,我们用`MinimalLogger`类当做`LoggerService` provider的令牌。
+makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','use-existing')
:marked
The `MinimalLogger` is an abstract class.
该`MinimalLogger`是一个抽象类。
+makeExample('cb-dependency-injection/ts/app/date-logger.service.ts','minimal-logger')(format='.')
:marked
We usually inherit from an abstract class.
But `LoggerService` doesn't inherit from `MinimalLogger`. *No class* inherits from it.
Instead, we use it like an interface.
我们通常从一个抽象类继承。但是`LoggerService`并不继承`MinimalLogger`。*没有类*继承它。取而代之,我们把它当接口来使用。
Look again at the declaration for `DateLoggerService`
请再看`DateLoggerService`的声明。
+makeExample('cb-dependency-injection/ts/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*.
`DateLoggerService`继承(延续)`LoggerService`,不是`MinimalLogger`。该`DateLoggerService`*实现*`MinimalLogger`,就像`MinimalLogger`是一个接口。
We call a class used in this way a ***class-interface***.
The key benefit of a *class-interface* is that we can get the strong-typing of an interface
and we can ***use it as a provider token*** in the same manner as a normal class.
我们称这种用法的类叫做*类-接口*。它关键的好处是一个*类-接口*给我们提供了一个接口的强类型,同时,我们能想正常类一样***使用它作为一个provider令牌***。
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.
一个***类-接口***应该*只*定义它的消费者容许调用的成员。这样一个窄的接口帮助我们分离该类的具体类实例和他的消费者。
该`MinimalLogger`只定义了两个`LoggerClass`的成员。
.l-sub-section
:marked
#### Why *MinimalLogger* is a class and not an interface
We 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.
### 为什么*MinimalLogger*是一个类而不是一个接口?因为我们不能把一个接口当做一个provider的令牌,因为接口不是JavaScript对象。
它们只存在在TypeScript的设计空间里。它们会在被编译到JavaScript之后消失。
A provider token must be a real JavaScript object of some kind:
a function, an object, a string ... a class.
一个provider令牌必须是一个真实的JavaScript对象,比如:一个函数,一个对象,一个字符串 ...一个类。
Using a class as an interface gives us the characteristics of an interface in a JavaScript object.
把一个类当做接口使用,为我们在一个JavaScript对象上提供了接口的特征。
The minimize memory cost, the class should have *no implementation*.
The `MinimalLogger` transpiles to this unoptimized, pre-minified JavaScript:
为了节省内存费用,该类不应该有*执行*。该`MinimalLogger`翻译到一个下面这个没有优化的,最小化之前的JavaScript:
+makeExample('cb-dependency-injection/ts/app/date-logger.service.ts','minimal-logger-transpiled')(format='.')
:marked
It never grows larger no matter how many members we 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.
We 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/app/hero-of-the-month.component.ts','provide-opaque-token')(format='.')
:marked
We created the `TITLE` token like this:
+makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','opaque-token')(format='.')
a(id="di-inheritance")
.l-main-section
:marked
## Inject into a derived class
We must take care when writing a component that inherits from another component.
If the base component has injected dependencies,
we 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/app/sorted-heroes.component.ts','heroes-base','app/sorted-heroes.component.ts (HeroesBaseComponent)')
.l-sub-section
:marked
We strongly prefer simple constructors. 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 we call the `HeroService` from within the `ngOnInit` rather than the constructor.
We explain the mysterious `_afterGetHeroes` below.
:marked
Users want to see the heroes in alphabetical order.
Rather than modify the original component, we sub-class it and create a
`SortedHeroesComponent` that sorts the heroes before presenting them.
The `SortedHeroesComponent` lets the base class fetch the heroes.
(we said it was contrived).
Unfortunately, Angular cannot inject the `HeroService` directly into the base class.
We must provide the `HeroService` again for *this* component,
then pass it down to the base class inside the constructor.
+makeExample('cb-dependency-injection/ts/app/sorted-heroes.component.ts','sorted-heroes','app/sorted-heroes.component.ts (SortedHeroesComponent)')
:marked
Now take note of the `_afterGetHeroes` method.
Our first instinct was 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 we'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.
We prefer the more loosely coupled techniques such as data binding and service sharing.
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
(checkout `Query`, `QueryList`, `ViewChildren`, and `ContentChildren`).
There is no public API for acquiring a parent reference.
But because every component instance is added to an injector's container,
we 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
We use standard class injection to acquire a parent component whose type we know.
In the following example, the parent `AlexComponent` has several children including a `CathyComponent`:
a(id='alex')
+makeExample('cb-dependency-injection/ts/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/app/parent-finder.component.ts','cathy','parent-finder.component.ts (CathyComponent)')(format='.')
:marked
We added the [@Optional](#optional) qualifier for safety but
the [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)
confirms that the `alex` parameter is set.
### Cannot find a parent by its base class
What if we do *not* 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 sound (cough) business reasons, this news component makes frequent calls
directly into its parent instrument as changing market data stream by.
The app probably defines more than a dozen financial instrument components.
If we're lucky, they all implement the same base class
whose API our `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 we could look for.
:marked
We're not claiming this is good design.
We are asking *can a component inject its parent via the parent's base class*?
The sample's `CraigComponent` explores this question. [Looking back](#alex)
we see that the `Alex` component *extends* (*inherits*) from a class named `Base`.
+makeExample('cb-dependency-injection/ts/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/app/parent-finder.component.ts','craig','parent-finder.component.ts (CraigComponent)')(format='.')
:marked
Unfortunately, this does not work.
The [live example](/resources/live-examples/cb-dependency-injection/ts/plnkr.html)
confirms that the `alex` parameter is null.
*We cannot inject a parent by its base class.*
### Find a parent by its class-interface
We 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 we could inject *Alex* into *Carol* [earlier](#known-parent).
We write an [*alias provider*](#useexisting) — a `provide` function 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/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 we 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 we've done it before:
+makeExample('cb-dependency-injection/ts/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
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/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 we're going to keep writing [*alias providers*](#useexisting) like this we should create a [helper function](#provideparent).
For now, focus on *Barry*'s constructor:
+makeTabs(
'cb-dependency-injection/ts/app/parent-finder.component.ts, cb-dependency-injection/ts/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 tell 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 we 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
We [learned earlier](#class-interface) that a *class-interface* is an abstract class used as an interface rather than as a base class.
Our example defines a `Parent` *class-interface* .
+makeExample('cb-dependency-injection/ts/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 narrowing 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/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/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/app/parent-finder.component.ts','alex-providers')(format='.')
:marked
We can extract that logic into a helper function like this:
+makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','provide-the-parent')(format='.')
:marked
Now we can add a simpler, more meaningful parent provider to our components:
+makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alice-providers')(format='.')
:marked
We can do better. The current version of the helper function can only alias the `Parent` *class-interface*.
Our 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/app/parent-finder.component.ts','provide-parent')(format='.')
:marked
And here's how we could use it with a different parent type:
+makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','beth-providers')(format='.')
:marked
a(id="forwardref")
.l-main-section
:marked
## Break circularities with a forward class reference (*forwardRef*)
The order of class declaration matters in TypeScript.
We can't refer directly to a class until it's been defined.
This isn't usually a problem, especially if we adhere to the recommended *one class per file* rule.
But sometimes circular references are unavoidable.
We'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.
In the [*Alex/Cathy* example](#known-parent) above:
* the `AlexComponent` lists the `CathyComponent` in its component metadata `directives` array
so it can display *Cathy* in its template.
* the `CathyComponent` constructor injects the parent `AlexComponent` which means that the `alex` parameter
of its constructor has the `AlexComponent` type.
*Alex* refers to *Cathy* and *Cathy* refers to *Alex*. We're stuck. We must define one of them first.
We defined *Alex* first and built its `C_DIRECTIVES` array with a forward reference to *Cathy*:
+makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','C_DIRECTIVES','parent-finder.component.ts (C_DIRECTIVES)')(format='.')
:marked
.l-sub-section
:marked
Defining *Alex* and *Cathy* in separate files won't help.
*Alex* would have to import *Cathy* and *Cathy* would have to import *Alex*.
We *had* to define *Alex* first because,
while we can add `forwardRef(CathyComponent)` to *Alex*'s `directives` array,
we can't write `public alex: forwardRef(AlexComponent))` in *Cathy*'s constructor.
:marked
We face a similar 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.
Again we break the circularity with `forwardRef`:
+makeExample('cb-dependency-injection/ts/app/parent-finder.component.ts','alex-providers','parent-finder.component.ts (AlexComponent providers)')(format='.')
:marked