parent
33f8120164
commit
1fac5f4eb1
@ -1,7 +1,6 @@
|
|||||||
import { BrowserModule } from '@angular/platform-browser';
|
import { BrowserModule } from '@angular/platform-browser';
|
||||||
import { NgModule } from '@angular/core';
|
import { NgModule } from '@angular/core';
|
||||||
import { FormsModule } from '@angular/forms';
|
import { FormsModule } from '@angular/forms';
|
||||||
|
|
||||||
import { AppComponent } from './app.component';
|
import { AppComponent } from './app.component';
|
||||||
import { HeroesComponent } from './heroes/heroes.component';
|
import { HeroesComponent } from './heroes/heroes.component';
|
||||||
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
|
import { HeroDetailComponent } from './hero-detail/hero-detail.component';
|
||||||
@ -19,13 +18,9 @@ import { MessagesComponent } from './messages/messages.component';
|
|||||||
FormsModule
|
FormsModule
|
||||||
],
|
],
|
||||||
// #docregion providers
|
// #docregion providers
|
||||||
// #docregion providers-heroservice
|
|
||||||
providers: [
|
providers: [
|
||||||
// #enddocregion providers-heroservice
|
|
||||||
// no need to place any providers due to the `providedIn` flag...
|
// no need to place any providers due to the `providedIn` flag...
|
||||||
// #docregion providers-heroservice
|
|
||||||
],
|
],
|
||||||
// #enddocregion providers-heroservice
|
|
||||||
// #enddocregion providers
|
// #enddocregion providers
|
||||||
bootstrap: [ AppComponent ]
|
bootstrap: [ AppComponent ]
|
||||||
})
|
})
|
||||||
|
@ -8,7 +8,9 @@ import { Hero } from './hero';
|
|||||||
import { HEROES } from './mock-heroes';
|
import { HEROES } from './mock-heroes';
|
||||||
|
|
||||||
// #docregion new
|
// #docregion new
|
||||||
@Injectable({providedIn: 'root'})
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
export class HeroService {
|
export class HeroService {
|
||||||
|
|
||||||
constructor() { }
|
constructor() { }
|
||||||
|
@ -14,7 +14,9 @@ import { HEROES } from './mock-heroes';
|
|||||||
import { MessageService } from './message.service';
|
import { MessageService } from './message.service';
|
||||||
// #enddocregion import-message-service
|
// #enddocregion import-message-service
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
export class HeroService {
|
export class HeroService {
|
||||||
|
|
||||||
// #docregion ctor
|
// #docregion ctor
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { Injectable } from '@angular/core';
|
import { Injectable } from '@angular/core';
|
||||||
|
|
||||||
@Injectable({ providedIn: 'root' })
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
export class MessageService {
|
export class MessageService {
|
||||||
messages: string[] = [];
|
messages: string[] = [];
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ Using the Angular CLI, create a service called `hero`.
|
|||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
The command generates skeleton `HeroService` class in `src/app/hero.service.ts`
|
The command generates skeleton `HeroService` class in `src/app/hero.service.ts`
|
||||||
The `HeroService` class should look like the below.
|
The `HeroService` class should look like the following example.
|
||||||
|
|
||||||
<code-example path="toh-pt4/src/app/hero.service.1.ts" region="new"
|
<code-example path="toh-pt4/src/app/hero.service.1.ts" region="new"
|
||||||
title="src/app/hero.service.ts (new service)" linenums="false">
|
title="src/app/hero.service.ts (new service)" linenums="false">
|
||||||
@ -40,19 +40,10 @@ The `HeroService` class should look like the below.
|
|||||||
### _@Injectable()_ services
|
### _@Injectable()_ services
|
||||||
|
|
||||||
Notice that the new service imports the Angular `Injectable` symbol and annotates
|
Notice that the new service imports the Angular `Injectable` symbol and annotates
|
||||||
the class with the `@Injectable()` decorator.
|
the class with the `@Injectable()` decorator. This marks the class as one that participates in the _dependency injection system_. The `HeroService` class is going to provide an injectable service, and it can also have its own injected dependencies.
|
||||||
|
It doesn't have any dependencies yet, but [it will soon](#inject-message-service).
|
||||||
|
|
||||||
The `@Injectable()` decorator tells Angular that this service _might_ itself
|
The `@Injectable()` decorator accepts a metadata object for the service, the same way the `@Component()` decorator did for your component classes.
|
||||||
have injected dependencies.
|
|
||||||
It doesn't have dependencies now but [it will soon](#inject-message-service).
|
|
||||||
Whether it does or it doesn't, it's good practice to keep the decorator.
|
|
||||||
|
|
||||||
<div class="l-sub-section">
|
|
||||||
|
|
||||||
The Angular [style guidelines](guide/styleguide#style-07-04) strongly recommend keeping it
|
|
||||||
and the linter enforces this rule.
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
### Get hero data
|
### Get hero data
|
||||||
|
|
||||||
@ -76,32 +67,39 @@ Add a `getHeroes` method to return the _mock heroes_.
|
|||||||
{@a provide}
|
{@a provide}
|
||||||
## Provide the `HeroService`
|
## Provide the `HeroService`
|
||||||
|
|
||||||
You must _provide_ the `HeroService` in the _dependency injection system_
|
You must make the `HeroService` available to the dependency injection system
|
||||||
before Angular can _inject_ it into the `HeroesComponent`,
|
before Angular can _inject_ it into the `HeroesComponent`,
|
||||||
as you will do [below](#inject).
|
as you will do [below](#inject). You do this by registering a _provider_. A provider is something that can create or deliver a service; in this case, it instantiates the `HeroService` class to provide the service.
|
||||||
|
|
||||||
There are several ways to provide the `HeroService`:
|
Now, you need to make sure that the `HeroService` is registered as the provider of this service.
|
||||||
in the `HeroesComponent`, in the `AppComponent`, in the `AppModule`.
|
You are registering it with an _injector_, which is the object that is responsible for choosing and injecting the provider where it is required.
|
||||||
Each option has pros and cons.
|
|
||||||
|
|
||||||
This tutorial chooses to provide it in the `AppModule`.
|
By default, the Angular CLI command `ng generate service` registers a provider with the _root injector_ for your service by including provider metadata in the `@Injectable` decorator.
|
||||||
|
|
||||||
That's such a popular choice that you could have told the CLI to provide it there automatically
|
If you look at the `@Injectable()` statement right before the `HeroService` class definition, you can see that the `providedIn` metadata value is 'root':
|
||||||
by appending `--module=app`.
|
|
||||||
|
```
|
||||||
|
@Injectable({
|
||||||
|
providedIn: 'root',
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
When you provide the service at the root level, Angular creates a single, shared instance of `HeroService` and injects into any class that asks for it.
|
||||||
|
Registering the provider in the `@Injectable` metadata also allows Angular to optimize an app by removing the service if it turns out not to be used after all.
|
||||||
|
|
||||||
|
<div class="l-sub-section">
|
||||||
|
|
||||||
|
If you need to, you can register providers at different levels:
|
||||||
|
in the `HeroesComponent`, in the `AppComponent`, in the `AppModule`.
|
||||||
|
For instance, you could have told the CLI to provide the service at the module level automatically by appending `--module=app`.
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
ng generate service hero --module=app
|
ng generate service hero --module=app
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Since you did not, you'll have to provide it yourself.
|
To learn more about providers and injectors, see the [Dependency Injection guide](guide/dependency-injection).
|
||||||
|
|
||||||
Open the `AppModule` class, import the `HeroService`, and add it to the `@NgModule.providers` array.
|
</div>
|
||||||
|
|
||||||
<code-example path="toh-pt4/src/app/app.module.ts" linenums="false" title="src/app/app.module.ts (providers)" region="providers-heroservice">
|
|
||||||
</code-example>
|
|
||||||
|
|
||||||
The `providers` array tells Angular to create a single, shared instance of `HeroService`
|
|
||||||
and inject into any class that asks for it.
|
|
||||||
|
|
||||||
The `HeroService` is now ready to plug into the `HeroesComponent`.
|
The `HeroService` is now ready to plug into the `HeroesComponent`.
|
||||||
|
|
||||||
@ -111,17 +109,12 @@ This is a interim code sample that will allow you to provide and use the `HeroSe
|
|||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="alert is-helpful">
|
|
||||||
|
|
||||||
Learn more about _providers_ in the [Providers](guide/providers) guide.
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
## Update `HeroesComponent`
|
## Update `HeroesComponent`
|
||||||
|
|
||||||
Open the `HeroesComponent` class file.
|
Open the `HeroesComponent` class file.
|
||||||
|
|
||||||
Delete the `HEROES` import as you won't need that anymore.
|
Delete the `HEROES` import, because you won't need that anymore.
|
||||||
Import the `HeroService` instead.
|
Import the `HeroService` instead.
|
||||||
|
|
||||||
<code-example path="toh-pt4/src/app/heroes/heroes.component.ts" title="src/app/heroes/heroes.component.ts (import HeroService)" region="hero-service-import">
|
<code-example path="toh-pt4/src/app/heroes/heroes.component.ts" title="src/app/heroes/heroes.component.ts (import HeroService)" region="hero-service-import">
|
||||||
@ -295,10 +288,9 @@ You should see the default paragraph from `MessagesComponent` at the bottom of t
|
|||||||
### Create the _MessageService_
|
### Create the _MessageService_
|
||||||
|
|
||||||
Use the CLI to create the `MessageService` in `src/app`.
|
Use the CLI to create the `MessageService` in `src/app`.
|
||||||
The `--module=app` option tells the CLI to [_provide_ this service](#provide) in the `AppModule`,
|
|
||||||
|
|
||||||
<code-example language="sh" class="code-shell">
|
<code-example language="sh" class="code-shell">
|
||||||
ng generate service message --module=app
|
ng generate service message
|
||||||
</code-example>
|
</code-example>
|
||||||
|
|
||||||
Open `MessageService` and replace its contents with the following.
|
Open `MessageService` and replace its contents with the following.
|
||||||
@ -442,7 +434,7 @@ Here are the code files discussed on this page and your app should look like thi
|
|||||||
## Summary
|
## Summary
|
||||||
|
|
||||||
* You refactored data access to the `HeroService` class.
|
* You refactored data access to the `HeroService` class.
|
||||||
* You _provided_ the `HeroService` in the root `AppModule` so that it can be injected anywhere.
|
* You registered the `HeroService` as the _provider_ of its service at the root level so that it can be injected anywhere in the app.
|
||||||
* You used [Angular Dependency Injection](guide/dependency-injection) to inject it into a component.
|
* You used [Angular Dependency Injection](guide/dependency-injection) to inject it into a component.
|
||||||
* You gave the `HeroService` _get data_ method an asynchronous signature.
|
* You gave the `HeroService` _get data_ method an asynchronous signature.
|
||||||
* You discovered `Observable` and the RxJS _Observable_ library.
|
* You discovered `Observable` and the RxJS _Observable_ library.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user