Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit e038870

Browse files
committed
docs(cb-di): more Ward tweaks
1 parent 16d2e8c commit e038870

File tree

4 files changed

+103
-32
lines changed

4 files changed

+103
-32
lines changed

public/docs/_examples/cb-dependency-injection/ts/app/app.component.ts

+12-9
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,29 @@ import { HeroesBaseComponent,
99
import { HighlightDirective } from './highlight.directive';
1010
import { ParentPasserComponent } from './parent-passer.component';
1111

12+
const DIRECTIVES = [
13+
HeroBiosComponent, HeroBiosAndContactsComponent,
14+
HeroesBaseComponent, SortedHeroesComponent,
15+
HeroOfTheMonthComponent,
16+
HighlightDirective,
17+
ParentPasserComponent
18+
];
19+
1220
// #docregion import-services
1321
import { LoggerService } from './logger.service';
1422
import { UserContextService } from './user-context.service';
1523
import { UserService } from './user.service';
16-
// #enddocregion import-services
1724

1825
@Component({
1926
selector: 'my-app',
2027
templateUrl:'app/app.component.html',
21-
directives: [
22-
HeroBiosComponent, HeroBiosAndContactsComponent,
23-
HeroesBaseComponent, SortedHeroesComponent,
24-
HeroOfTheMonthComponent,
25-
HighlightDirective,
26-
ParentPasserComponent
27-
],
28+
directives: DIRECTIVES,
2829
// #docregion providers
2930
providers: [LoggerService, UserContextService, UserService]
3031
// #enddocregion providers
3132
})
32-
3333
export class AppComponent {
34+
// #enddocregion import-services
3435

3536
private userId:number = 1;
3637

@@ -40,4 +41,6 @@ export class AppComponent {
4041
logger.logInfo('AppComponent initialized');
4142
}
4243
// #enddocregion ctor
44+
// #docregion import-services
4345
}
46+
// #enddocregion import-services

public/docs/_examples/cb-dependency-injection/ts/app/hero-bios.component.ts

+2
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ export class HeroBiosComponent{
4040
<hero-bio [heroId]="3"> <hero-contact></hero-contact> </hero-bio>`,
4141
// #enddocregion template
4242
directives:[HeroBioComponent, HeroContactComponent],
43+
// #docregion class-provider
4344
providers: [HeroService]
45+
// #enddocregion class-provider
4446
})
4547
export class HeroBiosAndContactsComponent{
4648
constructor(logger: LoggerService) {

public/docs/_examples/cb-dependency-injection/ts/app/hero-of-the-month.component.ts

+18-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1+
// #docplaster
12
// #docregion opaque-token
23
import {OpaqueToken} from 'angular2/core';
34

45
export const TITLE = new OpaqueToken('title');
56
// #enddocregion opaque-token
67

7-
// #docregion
8+
// #docregion hero-of-the-month
89
import { Component, Inject, provide } from 'angular2/core';
910

1011
import { DateLoggerService,
@@ -15,9 +16,12 @@ import { LoggerService } from './logger.service';
1516
import { RunnersUp } from './runners-up';
1617
import { runnersUpFactory } from './runners-up-provider.service';
1718

18-
@Component({
19-
selector:'hero-of-the-month',
20-
template:`
19+
// #enddocregion hero-of-the-month
20+
// #docregion some-hero
21+
const someHero = new Hero(42, 'Magma','Had a great month!','555-555-5555');
22+
// #enddocregion some-hero
23+
24+
const template = `
2125
<h3>{{title}}</h3>
2226
<div>Winner: <strong>{{_heroOfTheMonth.name}}</strong></div>
2327
<div>Reason for award: <strong>{{_heroOfTheMonth.description}}</strong></div>
@@ -27,13 +31,19 @@ import { runnersUpFactory } from './runners-up-provider.service';
2731
<div id="logs">
2832
<div *ngFor="#log of logs">{{log}}</div>
2933
</div>
30-
`,
34+
`;
3135

36+
// #docregion hero-of-the-month
37+
@Component({
38+
selector:'hero-of-the-month',
39+
template: template,
3240
// #docregion providers
3341
providers:[
34-
HeroService,
35-
provide(Hero, {useValue: new Hero(42, 'Magma','Had a great month!','555-555-5555')}),
42+
provide(Hero, {useValue: someHero}),
43+
// #docregion use-class
44+
provide(HeroService, {useClass: HeroService}),
3645
provide(LoggerService, {useClass: DateLoggerService}),
46+
// #enddocregion use-class
3747
provide(MinimalLogger, {useExisting: LoggerService}),
3848
provide(RunnersUp, {useFactory: runnersUpFactory, deps:[Hero, HeroService]}),
3949
provide(TITLE, {useValue: 'Hero of the Month'})
@@ -55,4 +65,4 @@ export class HeroOfTheMonthComponent {
5565
}
5666
}
5767
// #enddocregion class
58-
// #enddocregion
68+
// #enddocregion hero-of-the-month

public/docs/ts/latest/cookbook/dependency-injection.jade

+71-15
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,14 @@ include ../_util-fns
3535
## Application-wide dependencies
3636
Register providers for dependencies used throughout the application in the root application component, `AppComponent`.
3737

38-
In the following example we import and register several services
38+
In the following example, we import and register several services
3939
(the `LoggerService`, `UserContext`, and the `UserService`)
4040
in the `@Component` metadata `providers` array.
4141

42-
+makeExample('cb-dependency-injection/ts/app/app.component.ts','import-services','app/app.component.ts (imports)')(format='.')
43-
44-
+makeExample('cb-dependency-injection/ts/app/app.component.ts','providers','app/app.component.ts (providers)')
42+
+makeExample('cb-dependency-injection/ts/app/app.component.ts','import-services','app/app.component.ts (excerpt)')(format='.')
43+
.l-sub-section
44+
:marked
45+
Learn more about providers [below](#providers).
4546
:marked
4647
Now we can inject these services into the constructor of *any* application sub-component or service.
4748
+makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','ctor','app/hero-bios.component.ts (component constructor injection)')(format='.')
@@ -193,7 +194,8 @@ figure.image-display
193194
figure.image-display
194195
img(src="/resources/images/cookbooks/dependency-injection/hero-bios.png" alt="Bios")
195196

196-
<a id="qualify-dependency-lookup"></a>
197+
a(id="optional")
198+
a(id="qualify-dependency-lookup")
197199
.l-main-section
198200
:marked
199201
## Qualify dependency lookup with *@Optional* and *@Host*
@@ -283,21 +285,75 @@ figure.image-display
283285
.l-main-section
284286
:marked
285287
## Providers: defining dependency creation
286-
In the following sample we will show how to configure Angular's DI framework and control how instances are resolved.
287288

288-
A typical use case for wanting to customize DI is mocking. Mocks can be created for unit tests,
289-
but also to work ahead on a feature while we wait for other teams to build the services our components depend on.
290-
In the following example we will be building `HeroOfTheMonthComponent`
291-
where we customize the behavior of some of the services we introduced in previous sections.
292-
293-
+makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','','hero-of-the-month.component.ts')
289+
In this section we learn to write providers that deliver dependent services.
290+
291+
### Background
292+
We get a service from a dependency injector by giving it a ***token***.
293+
294+
We usually let Angular handle this transaction for us by specifying a constructor parameter and its type.
295+
The parameter type serves as the injector lookup *token*.
296+
Angular passes this token to the injector and assigns the result to the parameter.
297+
Here's a typical example:
294298

299+
+makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','ctor','app/hero-bios.component.ts (component constructor injection)')(format='.')
295300
:marked
296-
***useValue***
301+
Angular asks the injector for the service associated with the `LoggerService` and
302+
and assigns the returned value to the `logger` parameter.
297303

298-
We are using `useValue` to always return a specific hero whenever a `Hero` is injected.
304+
Where did the injector get that value?
305+
It may already have that value in its internal container.
306+
It it doesn't, it may be able to make one with the help of a ***provider***.
307+
A *provider* is a recipe for delivering a service associated with a *token*.
308+
.l-sub-section
309+
:marked
310+
If the injector doesn't have a provider for the requested *token*, it delegates the request
311+
to its parent injector, where the process repeats until there are no more injectors.
312+
If the search is futile, the injector throws an error ... unless the request was [optional](#optional).
313+
314+
Let's return our attention to providers themselves.
315+
:marked
316+
A new injector has no providers.
317+
Angular initializes the injectors it creates with some providers it cares about.
318+
We have to register our _own_ application providers manually,
319+
usually in the `providers` array of the `Component` or `Directive` metadata:
320+
+makeExample('cb-dependency-injection/ts/app/app.component.ts','providers','app/app.component.ts (providers)')
321+
:marked
322+
### Defining providers
323+
324+
The simple class provider is the most typical by far.
325+
We mention the class in the `providers` array and we're done.
326+
+makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts','class-provider','app/hero-bios.component.ts (class provider)')(format='.')
327+
:marked
328+
It's that simple because the most common injected service is an instance of a class.
329+
But not every dependency can be satisfied by creating a new instance of a class.
330+
We need other ways to deliver dependency values and that means we need other ways to specify a provider.
331+
332+
Here's a component we can talk about that demonstrates many of the alternatives and why we need them.
333+
+makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','hero-of-the-month','hero-of-the-month.component.ts')
334+
:marked
335+
#### provide
336+
The imported Angular `provide` function creates an instance of
337+
the Angular [Provider](../api/core/Provider-class.html) class.
299338

300-
***useClass***
339+
The `provide` function takes a *token* and a *definition object*.
340+
All but one (`TITLE`) of the tokens is a class name; we'll discuss `TITLE` in due course.
341+
342+
The *definition* object has one main property, (e.g. `useValue`) that indicates how the provider
343+
should create or return the provided value.
344+
345+
#### useValue
346+
347+
The `useValue` property supplies the value returned as the dependency.
348+
The value must be known *now*. Here it's an instance of the `Hero` class:
349+
+makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','some-hero')
350+
:marked
351+
#### useClass
352+
The `useClass` provider creates and returns new instance of the specified class.
353+
+makeExample('cb-dependency-injection/ts/app/hero-of-the-month.component.ts','use-class','hero-of-the-month.component.ts')
354+
:marked
355+
The first `HeroService` example is the *de-sugared*, expanded form of the most typical case in which the
356+
class to be created is also the token. We write it the long way only to de-mystify the preferred short form.
301357

302358
Previously we created `LoggerService`, but we are experimenting with a new logger,
303359
so in `HeroOfTheMonthComponent` we want to use `useClass` to return an instance of `DateLoggerService` whenever requesting a `LoggerService`.

0 commit comments

Comments
 (0)