docs(toh-4/ts): copyedits

closes #1638
This commit is contained in:
Patrice Chalin 2016-06-09 12:18:01 -07:00 committed by Ward Bell
parent 5adbfb9502
commit ca2e5c5d1d
6 changed files with 53 additions and 58 deletions

View File

@ -61,5 +61,3 @@ export class AppComponent implements OnInit {
onSelect(hero: Hero) { this.selectedHero = hero; } onSelect(hero: Hero) { this.selectedHero = hero; }
// #docregion on-init // #docregion on-init
} }
// #enddocregion on-init
// #enddocregion

View File

@ -6,7 +6,7 @@ import { Hero } from './hero';
selector: 'my-hero-detail', selector: 'my-hero-detail',
template: ` template: `
<div *ngIf="hero"> <div *ngIf="hero">
<h2>{{hero.name}} details</h2> <h2>{{hero.name}} details!</h2>
<div> <div>
<label>id: </label>{{hero.id}} <label>id: </label>{{hero.id}}
</div> </div>

View File

@ -6,18 +6,14 @@ import { Injectable } from '@angular/core';
// #enddocregion empty-class // #enddocregion empty-class
import { HEROES } from './mock-heroes'; import { HEROES } from './mock-heroes';
// #docregion empty-class // #docregion empty-class, getHeroes-stub
// #docregion getHeroes-stub
@Injectable() @Injectable()
export class HeroService { export class HeroService {
// #enddocregion empty-class // #enddocregion empty-class
getHeroes() { getHeroes() {
// #enddocregion getHeroes-stub // #enddocregion getHeroes-stub
return HEROES; return HEROES;
// #docregion getHeroes-stub // #docregion getHeroes-stub
} }
// #docregion empty-class // #docregion empty-class
} }
// #enddocregion getHeroes-stub
// #enddocregion empty-class
// #enddocregion

View File

@ -12,8 +12,8 @@ export class HeroService {
getHeroes() { getHeroes() {
return Promise.resolve(HEROES); return Promise.resolve(HEROES);
} }
// #enddocregion get-heroes // #enddocregion get-heroes, just-get-heroes
// #enddocregion just-get-heroes // #enddocregion
// See the "Take it slow" appendix // See the "Take it slow" appendix
// #docregion get-heroes-slowly // #docregion get-heroes-slowly
getHeroesSlowly() { getHeroesSlowly() {
@ -22,7 +22,6 @@ export class HeroService {
); );
} }
// #enddocregion get-heroes-slowly // #enddocregion get-heroes-slowly
// #docregion
// #docregion just-get-heroes // #docregion just-get-heroes
} }
// #enddocregion just-get-heroes
// #enddocregion

View File

@ -13,4 +13,3 @@ export var HEROES: Hero[] = [
{id: 19, name: 'Magma'}, {id: 19, name: 'Magma'},
{id: 20, name: 'Tornado'} {id: 20, name: 'Tornado'}
]; ];
// #enddocregion

View File

@ -13,7 +13,7 @@ include ../_util-fns
It also makes it easier to unit test the component with a mock service. It also makes it easier to unit test the component with a mock service.
Because data services are invariably asynchronous, Because data services are invariably asynchronous,
we'll finish the chapter with a promise-based version of the data service. we'll finish the chapter with a **!{_Promise}**-based version of the data service.
p Run the #[+liveExampleLink2('', 'toh-4')] for this part. p Run the #[+liveExampleLink2('', 'toh-4')] for this part.
@ -64,7 +64,7 @@ code-example(language="bash").
First, defining heroes is not the component's job. First, defining heroes is not the component's job.
Second, we can't easily share that list of heroes with other components and views. Second, we can't easily share that list of heroes with other components and views.
We can refactor this hero data acquisition business to a single service that provides heroes and We can refactor this hero data acquisition business to a single service that provides heroes, and
share that service with all components that need heroes. share that service with all components that need heroes.
### Create the HeroService ### Create the HeroService
@ -72,12 +72,12 @@ code-example(language="bash").
.l-sub-section .l-sub-section
:marked :marked
We've adopted a convention in which we spell the name of a service in lowercase followed by `.service`. We've adopted a convention in which we spell the name of a service in lowercase followed by `.service`.
If the service name were multi-word, we'd spell the base filename with lower dash case (AKA "kebab-case"). If the service name were multi-word, we'd spell the base filename in lower [dash-case](../guide/glossary.html#!#dash-case).
The `SpecialSuperHeroService` would be defined in the `special-super-hero.service.ts` file. The `SpecialSuperHeroService` would be defined in the `special-super-hero.service.ts` file.
:marked :marked
We name the class `HeroService` and export it for others to import. We name the class `HeroService` and export it for others to import.
+makeExample('toh-4/ts/app/hero.service.1.ts', 'empty-class', 'hero.service.ts (exported class)')(format=".") +makeExample('toh-4/ts/app/hero.service.1.ts', 'empty-class', 'app/hero.service.ts (starting point)')(format=".")
:marked :marked
### Injectable Services ### Injectable Services
@ -96,7 +96,7 @@ code-example(language="bash").
:marked :marked
### Getting Heroes ### Getting Heroes
Add a `getHeroes` method stub. Add a `getHeroes` method stub.
+makeExample('toh-4/ts/app/hero.service.1.ts', 'getHeroes-stub', 'hero.service.ts ( getHeroes stub)')(format=".") +makeExample('toh-4/ts/app/hero.service.1.ts', 'getHeroes-stub', 'app/hero.service.ts (getHeroes stub)')(format=".")
:marked :marked
We're holding back on the implementation for a moment to make an important point. We're holding back on the implementation for a moment to make an important point.
@ -117,30 +117,30 @@ code-example(language="bash").
Cut the `HEROES` array from `app.component.ts` and paste it to a new file in the `app` folder named `mock-heroes.ts`. Cut the `HEROES` array from `app.component.ts` and paste it to a new file in the `app` folder named `mock-heroes.ts`.
We copy the `import {Hero} ...` statement as well because the heroes array uses the `Hero` class. We copy the `import {Hero} ...` statement as well because the heroes array uses the `Hero` class.
+makeExample('toh-4/ts/app/mock-heroes.ts', null, 'mock-heroes.ts (Heroes array)') +makeExample('toh-4/ts/app/mock-heroes.ts', null, 'app/mock-heroes.ts')
:marked :marked
We export the `HEROES` constant so we can import it elsewhere &mdash; such as our `HeroService`. We export the `HEROES` constant so we can import it elsewhere &mdash; such as our `HeroService`.
Meanwhile, back in `app.component.ts` where we cut away the `HEROES` array, Meanwhile, back in `app.component.ts` where we cut away the `HEROES` array,
we leave behind an uninitialized `heroes` property: we leave behind an uninitialized `heroes` property:
+makeExample('toh-4/ts/app/app.component.1.ts', 'heroes-prop', 'app.component.ts (heroes property)')(format=".") +makeExample('toh-4/ts/app/app.component.1.ts', 'heroes-prop', 'app/app.component.ts (heroes property)')(format=".")
:marked :marked
### Return Mocked Heroes ### Return Mocked Heroes
Back in the `HeroService` we import the mock `HEROES` and return it from the `getHeroes` method. Back in the `HeroService` we import the mock `HEROES` and return it from the `getHeroes` method.
Our `HeroService` looks like this: Our `HeroService` looks like this:
+makeExample('toh-4/ts/app/hero.service.1.ts', null, 'hero.service.ts')(format=".") +makeExample('toh-4/ts/app/hero.service.1.ts', null, 'app/hero.service.ts')(format=".")
:marked :marked
### Use the Hero Service ### Use the Hero Service
We're ready to use the `HeroService` in other components starting with our `AppComponent`. We're ready to use the `HeroService` in other components starting with our `AppComponent`.
We begin, as usual, by importing the thing we want to use, the `HeroService`. We begin, as usual, by importing the thing we want to use, the `HeroService`.
+makeExample('toh-4/ts/app/app.component.ts', 'hero-service-import', 'app.component.ts (import HeroService)') +makeExcerpt('toh-4/ts/app/app.component.ts', 'hero-service-import')
:marked :marked
Importing the service allows us to *reference* it in our code. Importing the service allows us to *reference* it in our code.
How should the `AppComponent` acquire a runtime concrete `HeroService` instance? How should the `AppComponent` acquire a runtime concrete `HeroService` instance?
### Do we *new* the *HeroService*? No way! ### Do we *new* the *HeroService*? No way!
We could create a new instance of the `HeroService` with "new" like this: We could create a new instance of the `HeroService` with `new` like this:
+makeExample('toh-4/ts/app/app.component.1.ts', 'new-service')(format=".") +makeExample('toh-4/ts/app/app.component.1.ts', 'new-service')(format=".")
:marked :marked
That's a bad idea for several reasons including That's a bad idea for several reasons including
@ -150,7 +150,7 @@ code-example(language="bash").
we'll have to find every place we create the service and fix it. we'll have to find every place we create the service and fix it.
Running around patching code is error prone and adds to the test burden. Running around patching code is error prone and adds to the test burden.
* We create a new service each time we use "new". * We create a new service each time we use `new`.
What if the service should cache heroes and share that cache with others? What if the service should cache heroes and share that cache with others?
We couldn't do that. We couldn't do that.
@ -168,11 +168,11 @@ code-example(language="bash").
### Inject the *HeroService* ### Inject the *HeroService*
Two lines replace the one line that created with *new*: Two lines replace the one line that created with *new*:
1. we add a constructor. 1. We add a constructor that also defines a private property.
1. we add to the component's `providers` metadata 1. We add to the component's `providers` metadata.
Here's the constructor: Here's the constructor:
+makeExample('toh-4/ts/app/app.component.1.ts', 'ctor', 'app.component.ts (constructor)') +makeExample('toh-4/ts/app/app.component.1.ts', 'ctor', 'app/app.component.ts (constructor)')
:marked :marked
The constructor itself does nothing. The parameter simultaneously The constructor itself does nothing. The parameter simultaneously
defines a private `heroService` property and identifies it as a `HeroService` injection site. defines a private `heroService` property and identifies it as a `HeroService` injection site.
@ -185,14 +185,14 @@ code-example(language="bash").
:marked :marked
The *injector* does not know yet how to create a `HeroService`. The *injector* does not know yet how to create a `HeroService`.
If we ran our code now, Angular would fail with an error: If we ran our code now, Angular would fail with an error:
code-example(format="." language="html"). code-example(format="nocode").
EXCEPTION: No provider for HeroService! (AppComponent -> HeroService) EXCEPTION: No provider for HeroService! (AppComponent -> HeroService)
:marked :marked
We have to teach the *injector* how to make a `HeroService` by registering a `HeroService` **provider**. We have to teach the *injector* how to make a `HeroService` by registering a `HeroService` **provider**.
Do that by adding the following `providers` array property to the bottom of the component metadata Do that by adding the following `providers` array property to the bottom of the component metadata
in the `@Component` call. in the `@Component` call.
+makeExample('toh-4/ts/app/app.component.1.ts', 'providers', 'app.component.ts (providing HeroService)') +makeExcerpt('toh-4/ts/app/app.component.1.ts', 'providers')
:marked :marked
The `providers` array tells Angular to create a fresh instance of the `HeroService` when it creates a new `AppComponent`. The `providers` array tells Angular to create a fresh instance of the `HeroService` when it creates a new `AppComponent`.
The `AppComponent` can use that service to get heroes and so can every child component of its component tree. The `AppComponent` can use that service to get heroes and so can every child component of its component tree.
@ -205,7 +205,7 @@ a#child-component
+makeExample('toh-4/ts/app/app.component.1.ts', 'get-heroes')(format=".") +makeExample('toh-4/ts/app/app.component.1.ts', 'get-heroes')(format=".")
:marked :marked
We don't really need a dedicated method to wrap one line. We write it anyway: We don't really need a dedicated method to wrap one line. We write it anyway:
+makeExample('toh-4/ts/app/app.component.1.ts', 'getHeroes', 'app.component.ts (getHeroes)')(format=".") +makeExcerpt('toh-4/ts/app/app.component.1.ts', 'getHeroes')
<a id="oninit"></a> <a id="oninit"></a>
:marked :marked
@ -232,18 +232,19 @@ a#child-component
Learn more about lifecycle hooks in the [Lifecycle Hooks](../guide/lifecycle-hooks.html) chapter. Learn more about lifecycle hooks in the [Lifecycle Hooks](../guide/lifecycle-hooks.html) chapter.
:marked :marked
Here's the essential outline for the `OnInit` interface: Here's the essential outline for the `OnInit` interface:
+makeExample('toh-4/ts/app/app.component.1.ts', 'on-init', 'app.component.ts (OnInit protocol)')(format=".") +makeExample('toh-4/ts/app/app.component.1.ts', 'on-init', 'app/app.component.ts (ngOnInit stub)')(format=".")
:marked :marked
We write an `ngOnInit` method with our initialization logic inside and leave it to Angular to call it We write an `ngOnInit` method with our initialization logic inside and leave it to Angular to call it
at the right time. In our case, we initialize by calling `getHeroes`. at the right time. In our case, we initialize by calling `getHeroes`.
+makeExample('toh-4/ts/app/app.component.1.ts', 'ng-on-init', 'app.component.ts (OnInit protocol)')(format=".") +makeExcerpt('toh-4/ts/app/app.component.1.ts', 'ng-on-init')
:marked :marked
Our application should be running as expected, showing a list of heroes and a hero detail view Our application should be running as expected, showing a list of heroes and a hero detail view
when we click on a hero name. when we click on a hero name.
We're getting closer. But something isn't quite right. We're getting closer. But something isn't quite right.
## Async Services and Promises <a id="async"></a>
## Async Services and !{_Promise}s
Our `HeroService` returns a list of mock heroes immediately. Our `HeroService` returns a list of mock heroes immediately.
Its `getHeroes` signature is synchronous Its `getHeroes` signature is synchronous
+makeExample('toh-4/ts/app/app.component.1.ts', 'get-heroes')(format=".") +makeExample('toh-4/ts/app/app.component.1.ts', 'get-heroes')(format=".")
@ -257,34 +258,34 @@ a#child-component
We'll have to use some kind of asynchronous technique and that will change the signature of our `getHeroes` method. We'll have to use some kind of asynchronous technique and that will change the signature of our `getHeroes` method.
We'll use *promises*. We'll use *!{_Promise}s*.
### The Hero Service makes a promise ### The Hero Service makes a !{_Promise}
A **promise** is ... well it's a promise to call us back later when the results are ready. A **!{_Promise}** is ... well it's a promise to call us back later when the results are ready.
We ask an asynchronous service to do some work and give it a callback function. We ask an asynchronous service to do some work and give it a callback function.
It does that work (somewhere) and eventually it calls our function with the results of the work or an error. It does that work (somewhere) and eventually it calls our function with the results of the work or an error.
.l-sub-section .l-sub-section
:marked :marked
We are simplifying. Learn about ES2015 Promises [here](http://exploringjs.com/es6/ch_promises.html) and elsewhere on the web. We are simplifying. Learn about ES2015 Promises [here](http://exploringjs.com/es6/ch_promises.html) and elsewhere on the web.
:marked :marked
Update the `HeroService` with this promise-returning `getHeroes` method: Update the `HeroService` with this !{_Promise}-returning `getHeroes` method:
+makeExample('toh-4/ts/app/hero.service.ts', 'get-heroes', 'hero.service.ts (getHeroes)')(format=".") +makeExample('toh-4/ts/app/hero.service.ts', 'get-heroes', 'app/hero.service.ts (excerpt)')(format=".")
:marked :marked
We're still mocking the data. We're simulating the behavior of an ultra-fast, zero-latency server, We're still mocking the data. We're simulating the behavior of an ultra-fast, zero-latency server,
by returning an **immediately resolved promise** with our mock heroes as the result. by returning an **immediately resolved !{_Promise}** with our mock heroes as the result.
### Act on the Promise ### Act on the !{_Promise}
Returning to the `AppComponent` and its `getHeroes` method, we see that it still looks like this: Returning to the `AppComponent` and its `getHeroes` method, we see that it still looks like this:
+makeExample('toh-4/ts/app/app.component.1.ts', 'getHeroes', 'app.component.ts (getHeroes - old)')(format=".") +makeExample('toh-4/ts/app/app.component.1.ts', 'getHeroes', 'app/app.component.ts (getHeroes - old)')(format=".")
:marked :marked
As a result of our change to `HeroService`, we're now setting `this.heroes` to a promise rather than an array of heroes. As a result of our change to `HeroService`, we're now setting `this.heroes` to a !{_Promise} rather than an array of heroes.
We have to change our implementation to *act on the promise when it resolves*. We have to change our implementation to *act on the !{_Promise} when it resolves*.
When the promise resolves successfully, *then* we will have heroes to display. When the !{_Promise} resolves successfully, *then* we will have heroes to display.
We pass our callback function as an argument to the promise's **then** method: We pass our callback function as an argument to the !{_Promise}'s **then** method:
+makeExample('toh-4/ts/app/app.component.ts', 'get-heroes', 'app.component.ts (getHeroes - revised)')(format=".") +makeExample('toh-4/ts/app/app.component.ts', 'get-heroes', 'app/app.component.ts (getHeroes - revised)')(format=".")
.l-sub-section .l-sub-section
:marked :marked
The [ES2015 arrow function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) The [ES2015 arrow function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions)
@ -316,6 +317,8 @@ a#child-component
.file typings ... .file typings ...
.file index.html .file index.html
.file package.json .file package.json
.file styles.css
.file systemjs.config.js
.file tsconfig.json .file tsconfig.json
.file typings.json .file typings.json
:marked :marked
@ -334,11 +337,11 @@ a#child-component
## The Road Weve Travelled ## The Road Weve Travelled
Lets take stock of what weve built. Lets take stock of what weve built.
* We created a service class that can be shared by many components * We created a service class that can be shared by many components.
* We used the `ngOnInit` Lifecycle Hook to get our heroes when our `AppComponent` activates * We used the `ngOnInit` Lifecycle Hook to get our heroes when our `AppComponent` activates.
* We defined our `HeroService` as a provider for our `AppComponent` * We defined our `HeroService` as a provider for our `AppComponent`.
* We created mock hero data and imported them into our service * We created mock hero data and imported them into our service.
* We designed our service to return a promise and our component to get our data from the promise * We designed our service to return a !{_Promise} and our component to get our data from the !{_Promise}.
p Run the #[+liveExampleLink2('', 'toh-4')] for this part. p Run the #[+liveExampleLink2('', 'toh-4')] for this part.
:marked :marked
@ -357,10 +360,10 @@ p Run the #[+liveExampleLink2('', 'toh-4')] for this part.
We can simulate a slow connection. We can simulate a slow connection.
Import the `Hero` symbol and add the following `getHeroesSlowly` method to the `HeroService` Import the `Hero` symbol and add the following `getHeroesSlowly` method to the `HeroService`
+makeExample('toh-4/ts/app/hero.service.ts', 'get-heroes-slowly', 'hero.service.ts (getHeroesSlowly)')(format=".") +makeExample('toh-4/ts/app/hero.service.ts', 'get-heroes-slowly', 'app/hero.service.ts (getHeroesSlowly)')(format=".")
:marked :marked
Like `getHeroes`, it also returns a promise. Like `getHeroes`, it also returns a !{_Promise}.
But this promise waits 2 seconds before resolving the promise with mock heroes. But this !{_Promise} waits 2 seconds before resolving the !{_Promise} with mock heroes.
Back in the `AppComponent`, replace `heroService.getHeroes` with `heroService.getHeroesSlowly` Back in the `AppComponent`, replace `heroService.getHeroes` with `heroService.getHeroesSlowly`
and see how the app behaves. and see how the app behaves.