"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "aio/content/guide/dependency-injection-in-action.md" between
angular-11.0.1.tar.gz and angular-11.0.2.tar.gz

About: Angular is a development platform for building mobile and desktop web applications using Typescript/JavaScript.

dependency-injection-in-action.md  (angular-11.0.1):dependency-injection-in-action.md  (angular-11.0.2)
# Dependency injection in action # Dependency injection in action
This section explores many of the features of dependency injection (DI) in Angul This guide explores many of the features of dependency injection (DI) in Angular
ar. .
{@a toc}
See the <live-example name="dependency-injection-in-action"></live-example>
of the code in this cookbook.
{@a nested-dependencies}
## Nested service dependencies
The _consumer_ of an injected service doesn't need to know how to create that se
rvice.
It's the job of the DI framework to create and cache dependencies. The consumer
just
needs to let the DI framework know which dependencies it needs.
Sometimes a service depends on other services, which may depend on yet other ser
vices.
The dependency injection framework resolves these nested dependencies in the cor
rect order.
At each step, the consumer of dependencies declares what it requires in its
constructor, and lets the framework provide them.
The following example shows that `AppComponent` declares its dependence on `Logg
erService` and `UserContext`.
<code-example path="dependency-injection-in-action/src/app/app.component.ts" reg
ion="ctor" header="src/app/app.component.ts"></code-example>
`UserContext` in turn depends on both `LoggerService` and
`UserService`, another service that gathers information about a particular user.
<code-example path="dependency-injection-in-action/src/app/user-context.service.
ts" region="injectables" header="user-context.service.ts (injection)"></code-exa
mple>
When Angular creates `AppComponent`, the DI framework creates an instance of `Lo
ggerService` and starts to create `UserContextService`.
`UserContextService` also needs `LoggerService`, which the framework already has
, so the framework can provide the same instance. `UserContextService` also need
s `UserService`, which the framework has yet to create. `UserService` has no fur
ther dependencies, so the framework can simply use `new` to instantiate the clas
s and provide the instance to the `UserContextService` constructor.
The parent `AppComponent` doesn't need to know about the dependencies of depende
ncies.
Declare what's needed in the constructor (in this case `LoggerService` and `User
ContextService`)
and the framework resolves the nested dependencies.
When all dependencies are in place, `AppComponent` displays the user information
.
<div class="lightbox">
<img src="generated/images/guide/dependency-injection-in-action/logged-in-user
.png" alt="Logged In User">
</div>
{@a service-scope}
## Limit service scope to a component subtree
An Angular application has multiple injectors, arranged in a tree hierarchy that
parallels the component tree.
Each injector creates a singleton instance of a dependency.
That same instance is injected wherever that injector provides that service.
A particular service can be provided and created at any level of the injector hi
erarchy,
which means that there can be multiple instances of a service if it is provided
by multiple injectors.
Dependencies provided by the root injector can be injected into *any* component
*anywhere* in the application.
In some cases, you might want to restrict service availability to a particular r
egion of the application.
For instance, you might want to let users explicitly opt in to use a service,
rather than letting the root injector provide it automatically.
You can limit the scope of an injected service to a *branch* of the application
hierarchy
by providing that service *at the sub-root component for that branch*.
This example shows how to make a different instance of `HeroService` available t
o `HeroesBaseComponent`
by adding it to the `providers` array of the `@Component()` decorator of the sub
-component.
<code-example path="dependency-injection-in-action/src/app/sorted-heroes.compone
nt.ts" region="injection" header="src/app/sorted-heroes.component.ts (HeroesBase
Component excerpt)">
</code-example>
When Angular creates `HeroesBaseComponent`, it also creates a new instance of `H
eroService`
that is visible only to that component and its children, if any.
You could also provide `HeroService` to a different component elsewhere in the a
pplication.
That would result in a different instance of the service, living in a different
injector.
<div class="alert is-helpful"> <div class="alert is-helpful">
Examples of such scoped `HeroService` singletons appear throughout the accompany See the <live-example></live-example> for a working example containing the code
ing sample code, snippets in this guide.
including `HeroBiosComponent`, `HeroOfTheMonthComponent`, and `HeroesBaseCompone
nt`.
Each of these components has its own `HeroService` instance managing its own ind
ependent collection of heroes.
</div> </div>
{@a multiple-service-instances} {@a multiple-service-instances}
## Multiple service instances (sandboxing) ## Multiple service instances (sandboxing)
Sometimes you want multiple instances of a service at *the same level* of the co mponent hierarchy. Sometimes you want multiple instances of a service at *the same level* of the co mponent hierarchy.
A good example is a service that holds state for its companion component instanc e. A good example is a service that holds state for its companion component instanc e.
skipping to change at line 262 skipping to change at line 191
Using the `@Self` decorator, the injector only looks at the component's injector for its providers. The `@SkipSelf` decorator allows you to skip the local injec tor and look up in the hierarchy to find a provider that satisfies this dependen cy. The `sessionStorageService` instance interacts with the `BrowserStorageServi ce` using the `sessionStorage` browser API, while the `localStorageService` skip s the local injector and uses the root `BrowserStorageService` that uses the `lo calStorage` browser API. Using the `@Self` decorator, the injector only looks at the component's injector for its providers. The `@SkipSelf` decorator allows you to skip the local injec tor and look up in the hierarchy to find a provider that satisfies this dependen cy. The `sessionStorageService` instance interacts with the `BrowserStorageServi ce` using the `sessionStorage` browser API, while the `localStorageService` skip s the local injector and uses the root `BrowserStorageService` that uses the `lo calStorage` browser API.
{@a component-element} {@a component-element}
## Inject the component's DOM element ## Inject the component's DOM element
Although developers strive to avoid it, many visual effects and third-party tool s, such as jQuery, Although developers strive to avoid it, many visual effects and third-party tool s, such as jQuery,
require DOM access. require DOM access.
As a result, you might need to access a component's DOM element. As a result, you might need to access a component's DOM element.
To illustrate, here's a simplified version of `HighlightDirective` from To illustrate, here's a minimal version of `HighlightDirective` from
the [Attribute Directives](guide/attribute-directives) page. the [Attribute Directives](guide/attribute-directives) page.
<code-example path="dependency-injection-in-action/src/app/highlight.directive.t s" header="src/app/highlight.directive.ts"> <code-example path="dependency-injection-in-action/src/app/highlight.directive.t s" header="src/app/highlight.directive.ts">
</code-example> </code-example>
The directive sets the background to a highlight color when the user mouses over the The directive sets the background to a highlight color when the user mouses over the
DOM element to which the directive is applied. DOM element to which the directive is applied.
Angular sets the constructor's `el` parameter to the injected `ElementRef`. Angular sets the constructor's `el` parameter to the injected `ElementRef`.
skipping to change at line 286 skipping to change at line 215
The sample code applies the directive's `myHighlight` attribute to two `<div>` t ags, The sample code applies the directive's `myHighlight` attribute to two `<div>` t ags,
first without a value (yielding the default color) and then with an assigned col or value. first without a value (yielding the default color) and then with an assigned col or value.
<code-example path="dependency-injection-in-action/src/app/app.component.html" r egion="highlight" header="src/app/app.component.html (highlight)"></code-example > <code-example path="dependency-injection-in-action/src/app/app.component.html" r egion="highlight" header="src/app/app.component.html (highlight)"></code-example >
The following image shows the effect of mousing over the `<hero-bios-and-contact s>` tag. The following image shows the effect of mousing over the `<hero-bios-and-contact s>` tag.
<div class="lightbox"> <div class="lightbox">
<img src="generated/images/guide/dependency-injection-in-action/highlight.png" alt="Highlighted bios"> <img src="generated/images/guide/dependency-injection-in-action/highlight.png" alt="Highlighted bios">
</div> </div>
{@a providers}
## Define dependencies with providers
This section demonstrates how to write providers that deliver dependent services
.
In order to get a service from a dependency injector, you have to give it a [tok
en](guide/glossary#token).
Angular usually handles this transaction by specifying a constructor parameter a
nd its type.
The parameter type serves as the injector lookup token.
Angular passes this token to the injector and assigns the result to the paramete
r.
The following is a typical example.
<code-example path="dependency-injection-in-action/src/app/hero-bios.component.t
s" region="ctor" header="src/app/hero-bios.component.ts (component constructor i
njection)"></code-example>
Angular asks the injector for the service associated with `LoggerService`
and assigns the returned value to the `logger` parameter.
If the injector has already cached an instance of the service associated with th
e token,
it provides that instance.
If it doesn't, it needs to make one using the provider associated with the token
.
<div class="alert is-helpful">
If the injector doesn't have a provider for a requested token, it delegates the
request
to its parent injector, where the process repeats until there are no more inject
ors.
If the search fails, the injector throws an error&mdash;unless the request was [
optional](guide/dependency-injection-in-action#optional).
</div>
A new injector has no providers.
Angular initializes the injectors it creates with a set of preferred providers.
You have to configure providers for your own app-specific dependencies.
{@a defining-providers} {@a defining-providers}
### Defining providers ### Defining providers
A dependency can't always be created by the default method of instantiating a cl ass. A dependency can't always be created by the default method of instantiating a cl ass.
You learned about some other methods in [Dependency Providers](guide/dependency- injection-providers). You learned about some other methods in [Dependency Providers](guide/dependency- injection-providers).
The following `HeroOfTheMonthComponent` example demonstrates many of the alterna tives and why you need them. The following `HeroOfTheMonthComponent` example demonstrates many of the alterna tives and why you need them.
It's visually simple: a few properties and the logs produced by a logger. It's visually simple: a few properties and the logs produced by a logger.
<div class="lightbox"> <div class="lightbox">
skipping to change at line 668 skipping to change at line 562
The *Parent Finder* sample is full of circular class references that are impossi ble to break. The *Parent Finder* sample is full of circular class references that are impossi ble to break.
You face this dilemma when a class makes *a reference to itself* You face this dilemma when a class makes *a reference to itself*
as does `AlexComponent` in its `providers` array. as does `AlexComponent` in its `providers` array.
The `providers` array is a property of the `@Component()` decorator function whi ch must The `providers` array is a property of the `@Component()` decorator function whi ch must
appear *above* the class definition. appear *above* the class definition.
Break the circularity with `forwardRef`. Break the circularity with `forwardRef`.
<code-example path="dependency-injection-in-action/src/app/parent-finder.compone nt.ts" region="alex-providers" header="parent-finder.component.ts (AlexComponent providers)"></code-example> <code-example path="dependency-injection-in-action/src/app/parent-finder.compone nt.ts" region="alex-providers" header="parent-finder.component.ts (AlexComponent providers)"></code-example>
<!--- Waiting for good examples
{@a directive-level-providers}
{@a element-level-providers}
## Element-level providers
A component is a specialization of directive, and the `@Component()` decorator i
nherits the `providers` property from `@Directive`. The injector is at the eleme
nt level, so a provider configured with any element-level injector is available
to any component, directive, or pipe attached to the same element.
Here's a live example that implements a custom form control, taking advantage of
an injector that is shared by a component and a directive on the same element.
https://stackblitz.com/edit/basic-form-control
The component, `custom-control`, configures a provider for the DI token `NG_VALU
E_ACCESSOR`.
In the template, the `FormControlName` directive is instantiated along with the
custom component.
It can inject the `NG_VALUE_ACCESSOR` dependency because they share the same inj
ector.
(Notice that this example also makes use of `forwardRef()` to resolve a circular
ity in the definitions.)
### Sharing a service among components
__NEED TO TURN THIS INTO FULL EXTERNAL EXAMPLE__
Suppose you want to share the same `HeroCacheService` among multiple components.
One way to do this is to create a directive.
```
<ng-container heroCache>
<hero-overview></hero-overview>
<hero-details></hero-details>
</ng-container>
```
Use the `@Directive()` decorator to configure the provider for the service:
```
@Directive(providers:[HeroCacheService])
class heroCache{...}
```
Because the injectors for both the overview and details components are children
of the injector created from the `heroCache` directive, they can inject things i
t provides.
If the `heroCache` directive provides the `HeroCacheService`, the two components
end up sharing them.
If you want to show only one of them, use the directive to make sure __??of what
??__.
`<hero-overview heroCache></hero-overview>`
--->
 End of changes. 5 change blocks. 
154 lines changed or deleted 5 lines changed or added

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)