@@ -35,13 +35,14 @@ include ../_util-fns
35
35
## Application-wide dependencies
36
36
Register providers for dependencies used throughout the application in the root application component, `AppComponent`.
37
37
38
- In the following example we import and register several services
38
+ In the following example, we import and register several services
39
39
(the `LoggerService`, `UserContext`, and the `UserService`)
40
40
in the `@Component` metadata `providers` array.
41
41
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).
45
46
:marked
46
47
Now we can inject these services into the constructor of *any* application sub-component or service.
47
48
+ 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
193
194
figure.image-display
194
195
img( src ="/resources/images/cookbooks/dependency-injection/hero-bios.png" alt ="Bios" )
195
196
196
- <a id =" qualify-dependency-lookup" ></a >
197
+ a( id ="optional" )
198
+ a( id ="qualify-dependency-lookup" )
197
199
.l-main-section
198
200
:marked
199
201
## Qualify dependency lookup with *@Optional* and *@Host*
@@ -283,21 +285,75 @@ figure.image-display
283
285
.l-main-section
284
286
:marked
285
287
## 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.
287
288
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:
294
298
299
+ + makeExample('cb-dependency-injection/ts/app/hero-bios.component.ts' ,'ctor' ,'app/hero-bios.component.ts (component constructor injection)' )( format ='.' )
295
300
: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.
297
303
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.
299
338
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.
301
357
302
358
Previously we created `LoggerService`, but we are experimenting with a new logger,
303
359
so in `HeroOfTheMonthComponent` we want to use `useClass` to return an instance of `DateLoggerService` whenever requesting a `LoggerService`.
0 commit comments