`标签中显示了组件的`hero.name`属性的值。
+ * `{{hero.name}}`[*插值表达式*](displaying-data.html#interpolation):在`
`标签中显示了组件的`hero.name`属性的值。
- * The `[hero]` [property binding](template-syntax.html#property-binding) passes the `selectedHero` from
+ * The `[hero]` [*property binding*](template-syntax.html#property-binding) passes the `selectedHero` from
the parent `HeroListComponent` to the `hero` property of the child `HeroDetailComponent`.
- * `[hero]`[属性绑定](template-syntax.html#property-binding):把父组件`HeroListComponent`的`selectedHero`传到子组件`HeroDetailComponent`的`hero`属性中。
+ * `[hero]`[*属性绑定*](template-syntax.html#property-binding):把父组件`HeroListComponent`的`selectedHero`传到子组件`HeroDetailComponent`的`hero`属性中。
- * The `(click)` [event binding](user-input.html#click) calls the Component's `selectHero` method when the user clicks
+ * The `(click)` [*event binding*](user-input.html#click) calls the Component's `selectHero` method when the user clicks
on a hero's name
- * `(click)`[事件绑定](user-input.html#click):当用户点击英雄的名字时,调用组件的`selectHero`方法。
+ * `(click)`[*事件绑定*](user-input.html#click):当用户点击英雄的名字时,调用组件的`selectHero`方法。
* **Two-way data binding** is an important fourth form
that combines property and event binding in a single notation using the `ngModel` directive.
@@ -996,7 +996,7 @@ code-example(language="javascript" linenumbers=".").
>把"42.33"显示为`$42.33`。
- >**[Testing](../testing/index.html)** - Angular provides a testing library for "unit testing" our application parts as they
+ >**[Testing](testing.html)** - Angular provides a testing library for "unit testing" our application parts as they
interact with the Angular framework.
- >**[Testing](../testing/index.html)** - Angular提供了一个测试库,在程序各个部分与Angular框架交互同时,用来“单元测试”它们。
+ >**[Testing](testing.html)** - Angular提供了一个测试库,在程序各个部分与Angular框架交互同时,用来“单元测试”它们。
diff --git a/public/docs/ts/latest/guide/component-styles.jade b/public/docs/ts/latest/guide/component-styles.jade
index d1a062edb5..5eca9009df 100644
--- a/public/docs/ts/latest/guide/component-styles.jade
+++ b/public/docs/ts/latest/guide/component-styles.jade
@@ -49,7 +49,7 @@ p 运行本章这些代码的#[+liveExampleLink2()]
只要需要,我们就可以指定任何选择器、规则和媒体查询。
One way to do this is to set the `styles` property in the component metadata.
- The `styles` property takes #{_an_array} of strings that contain CSS code.
+ The `styles` property takes #{_an} #{_array} of strings that contain CSS code.
Usually we give it one string as in this example:
它的实现方式之一,是在组件的元数据中设置`styles`属性。
diff --git a/public/docs/ts/latest/guide/dependency-injection.jade b/public/docs/ts/latest/guide/dependency-injection.jade
index 69bf41f53d..2df8140dd7 100644
--- a/public/docs/ts/latest/guide/dependency-injection.jade
+++ b/public/docs/ts/latest/guide/dependency-injection.jade
@@ -60,7 +60,7 @@ include ../_util-fns
We didn't care about `Engine` constructor parameters when we first wrote `Car`.
We don't really care about them now.
But we'll *have* to start caring because
- when the definion of `Engine` changes, our `Car` class must change.
+ when the definition of `Engine` changes, our `Car` class must change.
That makes `Car` brittle.
如果`Engine`类升级了,并且它的构造函数要求传入一个参数了,该怎么办?
diff --git a/public/docs/ts/latest/guide/forms.jade b/public/docs/ts/latest/guide/forms.jade
index 5eac4cc77c..1309687091 100644
--- a/public/docs/ts/latest/guide/forms.jade
+++ b/public/docs/ts/latest/guide/forms.jade
@@ -1066,9 +1066,10 @@ figure.image-display
重新运行应用。表单打开时,状态是有效的,按钮是可用的。
Now delete the *Name*. We violate the "name required" rule which
- is duely noted in our error message as before. And now the Submit button is also disabled.
+ is duly noted in our error message as before. And now the Submit button is also disabled.
现在,删除*姓名*。我们违反了“必填姓名”规则,它还是像以前那样显示了错误信息来提醒我们。同时,“提交”按钮也被禁用了。
+
Not impressed? Think about it for a moment. What would we have to do to
wire the button's enable/disabled state to the form's validity without Angular's help?
diff --git a/public/docs/ts/latest/guide/npm-packages.jade b/public/docs/ts/latest/guide/npm-packages.jade
index 2cfd190551..de805f5241 100644
--- a/public/docs/ts/latest/guide/npm-packages.jade
+++ b/public/docs/ts/latest/guide/npm-packages.jade
@@ -93,8 +93,8 @@ a(id="dependencies")
应用程序的`package.json`文件中,`dependencies`区下有三类包:
- * ***Features*** - Feature packages provide our application with framework and utility capabilites.
- * ***特性*** - 特性包为我们的应用程序提供了框架和工具方面的能力。
+ * ***Features*** - Feature packages provide our application with framework and utility capabilities.
+ * ***特性*** - 特性包为我们的应用程序提供了框架和工具方面的能力。
* ***Polyfills*** - Polyfills plug gaps in the browser's JavaScript implementation.
* ***填充(Polyfills)*** - 填充包弥合了不同浏览器上的JavaScript实现方面的差异。
@@ -290,8 +290,7 @@ a(id="why-peer-dependencies")
We don't have a *peerDependencies* section in the QuickStart `package.json`.
But Angular itself has a *peerDependencies* section in
- [*its* package.json](https://github.com/angular/angular/blob/master/modules/angular2/package.json)
- and that has important consequences for our application.
+ *its* package.json and that has important consequences for our application.
在“快速起步”的`package.json`文件中,并没有*peerDependencies*区。
但是Angular本身在[*它自己的* package.json](https://github.com/angular/angular/blob/master/modules/angular2/package.json)中有,
diff --git a/public/docs/ts/latest/guide/template-syntax.jade b/public/docs/ts/latest/guide/template-syntax.jade
index fc7ddf220b..8ead90679d 100644
--- a/public/docs/ts/latest/guide/template-syntax.jade
+++ b/public/docs/ts/latest/guide/template-syntax.jade
@@ -969,9 +969,11 @@ a(id="one-time-initialization")
### Property binding or interpolation?
### 属性绑定还是插值表达式?
- We often have a choice between interpolation and property binding. The following binding pairs do the same thing:
+ We often have a choice between interpolation and property binding.
+ The following binding pairs do the same thing:
- 我们通常得在插值表达式和属性绑定之间做出选择。下列这几对绑定做的事情完全相同:
+ 我们通常得在插值表达式和属性绑定之间做出选择。
+ 下列这几对绑定做的事情完全相同:
+makeExample('template-syntax/ts/app/app.component.html', 'property-binding-vs-interpolation')(format=".")
:marked
Interpolation is a convenient alternative for property binding in many cases.
@@ -989,6 +991,26 @@ a(id="one-time-initialization")
我们倾向于可读性,所以倾向于插值表达式。
我们建议建立组织级的代码风格规定,然后选择一种形式,既能遵循规则,又能让手头的任务做起来更自然。
+:marked
+ #### Content Security
+ #### 内容安全
+ Imagine the following *malicious content*.
+
+ 假设下面的*恶毒内容*
++makeExample('template-syntax/ts/app/app.component.ts', 'evil-title')(format=".")
+:marked
+ Fortunately, Angular data binding is on alert for dangerous HTML.
+ It *sanitizes* the values before displaying them.
+ It **will not** allow HTML with script tags to leak into the browser, neither with interpolation
+ nor property binding.
+
++makeExample('template-syntax/ts/app/app.component.html', 'property-binding-vs-interpolation-sanitization')(format=".")
+:marked
+ Interpolation handles the script tags differently than property binding but both approaches render the
+ content harmlessly.
+figure.image-display
+ img(src='/resources/images/devguide/template-syntax/evil-title.png' alt="evil title made safe" width='500px')
+
.l-main-section
:marked
diff --git a/public/docs/ts/latest/guide/webpack.jade b/public/docs/ts/latest/guide/webpack.jade
index c319703ee7..7ab72da8c2 100644
--- a/public/docs/ts/latest/guide/webpack.jade
+++ b/public/docs/ts/latest/guide/webpack.jade
@@ -368,7 +368,7 @@ a(id="common-configuration")
但是大多数`import`语句完全不会去引用扩展名。
所以我们要告诉Webpack如何通过查找匹配的文件来_解析_模块文件的加载请求:
- * an explicit extention (signified by the empty extension string, `''`) or
+ * an explicit extension (signified by the empty extension string, `''`) or
* 一个明确的扩展名(通过一个空白的扩展名字符串`''`标记出来),或者
* `.js` extension (for regular JavaScript files and pre-compiled TypeScript files) or
* `.js`扩展名(为了查找标准的JavaScript文件和预编译过的TypeScript文件),或者
@@ -512,7 +512,7 @@ a(id="development-configuration")
我们这些CSS默认情况下被埋没在JavaScript包儿中。`ExtractTextPlugin`会把它们提取成外部`.css`文件,
这样`HtmlWebpackPlugin`插件就会转而把一个<link>标签写进`index.html`了。
- Refer to the Webpack documentation for details on these and other configuation options in this file
+ Refer to the Webpack documentation for details on these and other configuration options in this file
要了解本文件中这些以及其它配置项的详情,请参阅Webpack文档。
diff --git a/public/docs/ts/latest/quickstart.jade b/public/docs/ts/latest/quickstart.jade
index 15515b5fee..0596104391 100644
--- a/public/docs/ts/latest/quickstart.jade
+++ b/public/docs/ts/latest/quickstart.jade
@@ -5,9 +5,6 @@ block includes
- var _prereq = 'Node.js'
- var _angular_browser_uri = '@angular/platform-browser-dynamic'
- var _angular_core_uri = '@angular/core'
- - var _appDir = 'app'
- - var _indexHtmlDir = 'project root'
- - var _indexHtmlDirCn = '项目的根'
:marked
Our QuickStart goal is to build and run a super-simple
diff --git a/public/docs/ts/latest/tutorial/toh-pt5.jade b/public/docs/ts/latest/tutorial/toh-pt5.jade
index 62d6a7ff8c..a3a2218a43 100644
--- a/public/docs/ts/latest/tutorial/toh-pt5.jade
+++ b/public/docs/ts/latest/tutorial/toh-pt5.jade
@@ -468,11 +468,11 @@ code-example(format="." language="bash").
:marked
We specify the path _all the way back to the application root_ — `app/` in this case —
because Angular doesn't support relative paths _by default_.
- We _can_ switch to [component-relative paths](../cookbook/component-relative-paths) if we prefer.
+ We _can_ switch to [component-relative paths](../cookbook/component-relative-paths.html) if we prefer.
我们指定的所有路径_都是相对于该应用的根目录(这里是`app/`)的_。
因为Angular_默认_不支持使用相对于当前模块的路径。
- 只要喜欢,我们也_可以_切换成[相对于组件的路径](../cookbook/component-relative-paths)模式。
+ 只要喜欢,我们也_可以_切换成[相对于组件的路径](../cookbook/component-relative-paths.html)模式。
:marked
Create that file with these contents:
@@ -719,9 +719,10 @@ code-example(format='').
这段代码的问题在于`HeroService`并没有一个叫`getHero`的方法,我们最好在别人报告应用出问题之前赶快修复它。
- Open `HeroService` and add the `getHero` method. It's trivial given that we're still faking data access:
+ Open `HeroService` and add a `getHero` method that filters the heroes list from `getHeroes` by `id`:
+
+ 打开`HeroService`,并添加一个`getHero`方法,用来通过`id`从`getHeros`过滤英雄列表:
- 打开`HeroService`,并添加一个`getHero`方法。对于我们的假数据存取逻辑来说,这点修改是微不足道的:
+makeExample('toh-5/ts/app/hero.service.ts', 'get-hero', 'app/hero.service.ts (getHero)')(format=".")
:marked
Return to the `HeroDetailComponent` to clean up loose ends.
diff --git a/public/docs/ts/latest/tutorial/toh-pt6.jade b/public/docs/ts/latest/tutorial/toh-pt6.jade
index a35ba9c98b..fb0298e43c 100644
--- a/public/docs/ts/latest/tutorial/toh-pt6.jade
+++ b/public/docs/ts/latest/tutorial/toh-pt6.jade
@@ -2,15 +2,15 @@ include ../_util-fns
:marked
# Getting and Saving Data with HTTP
-
- Our stakeholders appreciate our progress.
+
+ Our stakeholders appreciate our progress.
Now they want to get the hero data from a server, let users add, edit, and delete heroes,
and save these changes back to the server.
-
+
In this chapter we teach our application to make the corresponding http calls to a remote server's web api.
:marked
- [Run the live example](/resources/live-examples/toh-6/ts/plnkr.html).
-
+ [Run the live example](/resources/live-examples/toh-6/ts/plnkr.html).
+
.l-main-section
:marked
## Where We Left Off
@@ -27,25 +27,25 @@ code-example(format="." language="bash").
:marked
The application runs and updates automatically as we continue to build the Tour of Heroes.
-.l-main-section
+.l-main-section
:marked
## Prepare for Http
-
- `Http` is ***not*** a core Angular module.
+
+ `Http` is ***not*** a core Angular module.
It's Angular's optional approach to web access and it exists as a separate add-on module called `@angular/http`,
- shipped in a separate script file as part of the Angular npm package.
-
+ shipped in a separate script file as part of the Angular npm package.
+
Fortunately we're ready to import from `@angular/http` because `systemjs.config` configured *SystemJS* to load that library when we need it.
:marked
### Register (provide) *http* services
Our app will depend upon the Angular `http` service which itself depends upon other supporting services.
The `HTTP_PROVIDERS` array from `@angular/http` library holds providers for the complete set of http services.
-
+
We should be able to access these services from anywhere in the application.
So we register them in the `bootstrap` method of `main.ts` where we
launch the application and its root `AppComponent`.
-
+
+makeExample('toh-6/ts/app/main.ts','v1','app/main.ts (v1)')(format='.')
:marked
Notice that we supply the `HTTP_PROVIDERS` in an array as the second parameter to the `bootstrap` method.
@@ -57,19 +57,19 @@ code-example(format="." language="bash").
We generally recommend registering application-wide services in the root `AppComponent` *providers*.
Here we're registering in `main` for a special reason.
-
- Our application is in the early stages of development and far from ready for production.
+
+ Our application is in the early stages of development and far from ready for production.
We don't even have a web server that can handle requests for heroes.
Until we do, *we'll have to fake it*.
-
+
We're going to *trick* the http client into fetching and saving data from
a demo/development service, the *in-memory web api*.
-
+
The application itself doesn't need to know and shouldn't know about this.
So we'll slip the *in-memory web api* into the configuration *above* the `AppComponent`.
-
+
Here is a version of `main` that performs this trick
-+makeExample('toh-6/ts/app/main.ts', 'final', 'app/main.ts (final)')(format=".")
++makeExample('toh-6/ts/app/main.ts', 'final', 'app/main.ts (final)')(format=".")
:marked
We're replacing the default `XHRBackend`, the service that talks to the remote server,
@@ -81,55 +81,55 @@ code-example(format="." language="bash").
.alert.is-helpful
:marked
This chaper is an introduction to the Angular http client.
- Please don't be distracted by the details of this backend substitution. Just follow along with the example.
-
+ Please don't be distracted by the details of this backend substitution. Just follow along with the example.
+
Learn more later about the *in-memory web api* in the [Http chapter](../guide/server-communication.html#!#in-mem-web-api).
- Remember, the *in-memory web api* is only useful in the early stages of development and for demonstrations such as this Tour of Heroes.
+ Remember, the *in-memory web api* is only useful in the early stages of development and for demonstrations such as this Tour of Heroes.
Skip it when you have a real web api server.
.l-main-section
:marked
## Heroes and Http
-
+
Look at our current `HeroService` implementation
+makeExample('toh-4/ts/app/hero.service.ts', 'get-heroes', 'app/hero.service.ts (getHeroes - old)')(format=".")
:marked
- We returned a promise resolved with mock heroes.
+ We returned a promise resolved with mock heroes.
It may have seemed like overkill at the time, but we were anticipating the
day when we fetched heroes with an http client and we knew that would have to be an asynchronous operation.
-
+
That day has arrived! Let's convert `getHeroes()` to use Angular's `Http` client:
-
+
+makeExample('toh-6/ts/app/hero.service.ts', 'get-heroes', 'app/hero.service.ts (getHeroes using Http)')(format=".")
-
+
:marked
### Http Promise
We're still returning a promise but we're creating it differently.
-
+
The Angular `http.get` returns an RxJS `Observable`.
*Observables* are a powerful way to manage asynchronous data flows.
We'll learn about `Observables` *later*.
-
+
For *now* we get back on familiar ground by immediately converting that `Observable` to a `Promise` using the `toPromise` operator.
+makeExample('toh-6/ts/app/hero.service.ts', 'to-promise')(format=".")
:marked
Unfortunately, the Angular `Observable` doesn't have a `toPromise` operator ... not out of the box.
- The Angular `Observable` is a bare-bones implementation.
-
+ The Angular `Observable` is a bare-bones implementation.
+
There are scores of operators like `toPromise` that extend `Observable` with useful capabilities.
If we want those capabilities, we have to add the operators ourselves.
That's as easy as importing them from the RxJS library like this:
+makeExample('toh-6/ts/app/hero.service.ts', 'rxjs')(format=".")
:marked
- ### Extracting the data in the *then* callback
+ ### Extracting the data in the *then* callback
In the *promise*'s `then` callback we call the `json` method of the http `Response` to extract the
data within the response.
+makeExample('toh-6/ts/app/hero.service.ts', 'to-data')(format=".")
:marked
- That object returned by `json` has a single `data` property.
+ That object returned by `json` has a single `data` property.
The `data` property holds the array of *heroes* that the caller really wants.
So we grab that array and return it as the resolved promise value.
@@ -138,20 +138,20 @@ code-example(format="." language="bash").
Pay close attention to the shape of the data returned by the server.
This particular *in-memory web api* example happens to return an object with a `data` property.
Your api might return something else.
-
- Adjust the code to match *your web api*.
+
+ Adjust the code to match *your web api*.
:marked
- The caller is unaware of these machinations. It receives a promise of *heroes* just as it did before.
+ The caller is unaware of these machinations. It receives a promise of *heroes* just as it did before.
It has no idea that we fetched the heroes from the server.
It knows nothing of the twists and turns required to turn the http response into heroes.
Such is the beauty and purpose of delegating data access to a service like this `HeroService`.
:marked
### Error Handling
-
+
At the end of `getHeroes` we `catch` server failures and pass them to an error handler:
+makeExample('toh-6/ts/app/hero.service.ts', 'catch')(format=".")
:marked
- This is a critical step!
+ This is a critical step!
We must anticipate http failures as they happen frequently for reasons beyond our control.
+makeExample('toh-6/ts/app/hero.service.ts', 'error-handler', 'app/hero.service.ts (Error handler)')(format=".")
@@ -160,51 +160,51 @@ code-example(format="." language="bash").
We've also decided to return a user friendly form of the error to
to the caller in a rejected promise so that the caller can display a proper error message to the user.
-
+
### Promises are Promises
- Although we made significant *internal* changes to `getHeroes()`, the public signature did not change.
+ Although we made significant *internal* changes to `getHeroes()`, the public signature did not change.
We still return a promise. We won't have to update any of the components that call `getHeroes()`.
-.l-main-section
+.l-main-section
:marked
## Add, Edit, Delete
-
- Our stakeholders are incredibly pleased with the added flexibility from the api integration, but it doesn't stop there. Next we want to add the capability to add, edit and delete heroes.
-
- We'll complete `HeroService` by creating `post`, `put` and `delete` http calls to meet our new requirements.
+
+ Our stakeholders are incredibly pleased with the added flexibility from the api integration, but it doesn't stop there. Next we want to add the capability to add, edit and delete heroes.
+
+ We'll complete `HeroService` by creating `post`, `put` and `delete` http calls to meet our new requirements.
:marked
### Post
-
+
We are using `post` to add new heroes. Post requests require a little bit more setup than Get requests, but the format is as follows:
-
+
+makeExample('toh-6/ts/app/hero.service.ts', 'post-hero', 'app/hero.service.ts (post hero)')(format=".")
:marked
- Now we create a header and set the content type to `application/json`. We'll call `JSON.stringify` before we post to convert the hero object to a string.
-
+ Now we create a header and set the content type to `application/json`. We'll call `JSON.stringify` before we post to convert the hero object to a string.
+
### Put
-
+
`put` is used to edit a specific hero, but the structure is very similar to a `post` request. The only difference is that we have to change the url slightly by appending the id of the hero we want to edit.
+makeExample('toh-6/ts/app/hero.service.ts', 'put-hero', 'app/hero.service.ts (put hero)')(format=".")
:marked
### Delete
- `delete` is used to delete heroes and the format is identical to `put` except for the function name.
+ `delete` is used to delete heroes and the format is identical to `put` except for the function name.
+makeExample('toh-6/ts/app/hero.service.ts', 'delete-hero', 'app/hero.service.ts (delete hero)')(format=".")
:marked
We add a `catch` to handle our errors for all three cases.
-
+
:marked
### Save
We combine the call to the private `post` and `put` methods in a single `save` method. This simplifies the public api and makes the integration with `HeroDetailComponent` easier. `HeroService` determines which method to call based on the state of the `hero` object. If the hero already has an id we know it's an edit. Otherwise we know it's an add.
+makeExample('toh-6/ts/app/hero.service.ts', 'save', 'app/hero.service.ts (save hero)')(format=".")
-
+
:marked
After these additions our `HeroService` looks like this:
@@ -213,27 +213,30 @@ code-example(format="." language="bash").
.l-main-section
:marked
## Updating Components
-
- Loading heroes using `Http` required no changes outside of `HeroService`, but we added a few new features as well.
+
+ Loading heroes using `Http` required no changes outside of `HeroService`, but we added a few new features as well.
In the following section we will update our components to use our new methods to add, edit and delete heroes.
-
+
### Add/Edit in the *HeroDetailComponent*
- We already have `HeroDetailComponent` for viewing details about a specific hero. Add and Edit are natural extensions of the detail view, so we are able to reuse `DetailHeroComponent` with a few tweaks. The original component was created to render existing data, but to add new data we have to initialize the `hero` property to an empty `Hero` object.
-
+
+ We already have `HeroDetailComponent` for viewing details about a specific hero.
+ Add and Edit are natural extensions of the detail view, so we are able to reuse `HeroDetailComponent` with a few tweaks.
+ The original component was created to render existing data, but to add new data we have to initialize the `hero` property to an empty `Hero` object.
+
+makeExample('toh-6/ts/app/hero-detail.component.ts', 'ngOnInit', 'app/hero-detail.component.ts (ngOnInit)')(format=".")
:marked
In order to differentiate between add and edit we are adding a check to see if an id is passed in the url. If the id is absent we bind `HeroDetailComponent` to an empty `Hero` object. In either case, any edits made through the UI will be bound back to the same `hero` property.
The next step is to add a save method to `HeroDetailComponent` and call the corresponding save method in `HeroesService`.
-
+
+makeExample('toh-6/ts/app/hero-detail.component.ts', 'save', 'app/hero-detail.component.ts (save)')(format=".")
:marked
The same save method is used for both add and edit since `HeroService` will know when to call `post` vs `put` based on the state of the `Hero` object.
-
+
After we save a hero, we redirect the browser back to the to the previous page using the `goBack()` method.
-
+
+makeExample('toh-6/ts/app/hero-detail.component.ts', 'goback', 'app/hero-detail.component.ts (goBack)')(format=".")
:marked
@@ -241,58 +244,58 @@ code-example(format="." language="bash").
.l-sub-section
:marked
- The `emit` "handshake" between `HeroDetailComponent` and `HeroesComponent` is an example of component to component communication. This is a topic for another day, but we have detailed information in our
Component Interaction Cookbook
+ The `emit` "handshake" between `HeroDetailComponent` and `HeroesComponent` is an example of component to component communication. This is a topic for another day, but we have detailed information in our
Component Interaction Cookbook
:marked
Here is `HeroDetailComponent` with its new save button.
-
+
figure.image-display
img(src='/resources/images/devguide/toh/hero-details-save-button.png' alt="Hero Details With Save Button")
:marked
### Add/Delete in the *HeroesComponent*
-
+
The user can *add* a new hero by clicking a button and entering a name.
When the user clicks the *Add New Hero* button, we display the `HeroDetailComponent`.
We aren't navigating to the component so it won't receive a hero `id`;
As we noted above, that is the component's cue to create and present an empty hero.
-
+
Add the following HTML to the `heroes.component.html`, just below the hero list (the `*ngFor`).
+makeExample('toh-6/ts/app/heroes.component.html', 'add-hero', 'app/heroes.component.html (add)')(format=".")
:marked
The user can *delete* an existing hero by clicking a delete button next to the hero's name.
-
+
Add the following HTML to the `heroes.component.html` right after the name in the repeated `
` tag:
+makeExample('toh-6/ts/app/heroes.component.html', 'delete-hero', 'app/heroes.component.html (delete)')(format=".")
:marked
Now let's fix-up the `HeroesComponent` to support the *add* and *delete* actions in the template.
Let's start with *add*.
-
+
We're using the `HeroDetailComponent` to capture the new hero information.
We have to tell Angular about that by importing the `HeroDetailComponent` and referencing it in the component metadata `directives` array.
-+makeExample('toh-6/ts/app/heroes.component.ts', 'hero-detail-component', 'app/heroes.component.ts (HeroDetailComponent)')(format=".")
++makeExample('toh-6/ts/app/heroes.component.ts', 'hero-detail-component', 'app/heroes.component.ts (HeroDetailComponent)')(format=".")
.l-sub-section
:marked
These are the same lines that we removed in the previous [Routing](toh-pt5.html) chapter.
We didn't know at the time that we'd need the *HeroDetailComponent* again. So we tidied up.
-
+
Now we *must* put these lines back. If we don't, Angular will ignore the ``
tag and pushing the *Add New Hero* button will have no visible effect.
:marked
Next we implement the click handler for the *Add New Hero* button.
-+makeExample('toh-6/ts/app/heroes.component.ts', 'add', 'app/heroes.component.ts (add)')(format=".")
++makeExample('toh-6/ts/app/heroes.component.ts', 'add', 'app/heroes.component.ts (add)')(format=".")
:marked
The `HeroDetailComponent` does most of the work. All we do is toggle an `*ngIf` flag that
swaps it into the DOM when were add a hero and remove it from the DOM when the user is done.
-
+
The *delete* logic is a bit trickier.
+makeExample('toh-6/ts/app/heroes.component.ts', 'delete', 'app/heroes.component.ts (delete)')(format=".")
:marked
- Of course we delegate the persistence of hero deletion to the `HeroService`.
+ Of course we delegate the persistence of hero deletion to the `HeroService`.
But the component is still responsible for updating the display.
So the *delete* method removes the deleted hero from the list.
@@ -300,12 +303,12 @@ figure.image-display
### Let's see it
Here are the fruits of labor in action:
figure.image-display
- img(src='/resources/images/devguide/toh/toh-http.anim.gif' alt="Heroes List Editting w/ HTTP")
+ img(src='/resources/images/devguide/toh/toh-http.anim.gif' alt="Heroes List Editting w/ HTTP")
:marked
### Review the App Structure
Let’s verify that we have the following structure after all of our good refactoring in this chapter:
-
+
.filetree
.file angular2-tour-of-heroes
.children
@@ -335,20 +338,20 @@ figure.image-display
.file systemjs.config.json
.file tsconfig.json
.file typings.json
-
-.l-main-section
+
+.l-main-section
:marked
## Home Stretch
-
+
We are at the end of our journey for now, but we have accomplished a lot.
- We added the necessary dependencies to use Http in our application.
- We refactored HeroService to load heroes from an api.
- We extended HeroService to support post, put and delete calls.
- We updated our components to allow adding, editing and deleting of heroes.
- We configured an in-memory web api.
-
+
Below is a summary of the files we changed.
-
+
+makeTabs(
`toh-6/ts/app/app.component.ts,
toh-6/ts/app/heroes.component.ts,
@@ -363,5 +366,4 @@ figure.image-display
hero-detail.comp...ts,
hero-detail.comp...html,
hero.service.ts`
-)
-
+)
diff --git a/public/resources/images/devguide/template-syntax/evil-title.png b/public/resources/images/devguide/template-syntax/evil-title.png
new file mode 100644
index 0000000000..9c67d71894
Binary files /dev/null and b/public/resources/images/devguide/template-syntax/evil-title.png differ
diff --git a/tools/doc-shredder/doc-shredder.js b/tools/doc-shredder/doc-shredder.js
index e834071ea3..7575781c8e 100644
--- a/tools/doc-shredder/doc-shredder.js
+++ b/tools/doc-shredder/doc-shredder.js
@@ -198,7 +198,7 @@ var createShredMapPackage = function(mapOptions) {
.config(function(readFilesProcessor, extractPathsReader ) {
readFilesProcessor.fileReaders = [ extractPathsReader];
})
- // default configs - may be overriden
+ // default configs - may be overridden
.config(function(readFilesProcessor) {
// Specify the base path used when resolving relative paths to source and output files
readFilesProcessor.basePath = '/';