@@ -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
193194figure.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