docs(toh-6): fix broken 'Add Hero' and fill in instructional gaps

This commit is contained in:
Ward Bell 2016-05-19 19:00:20 -07:00
parent ba02c40b56
commit 3324bd944d
4 changed files with 68 additions and 45 deletions

View File

@ -5,14 +5,19 @@
<span class="hero-element">
<span class="badge">{{hero.id}}</span> {{hero.name}}
</span>
<!-- #docregion delete-hero -->
<button class="delete-button" (click)="delete(hero, $event)">Delete</button>
<!-- #enddocregion delete-hero -->
</li>
</ul>
<!-- #docregion add-hero -->
<button (click)="addHero()">Add New Hero</button>
<div *ngIf="addingHero">
<my-hero-detail (close)="close($event)"></my-hero-detail>
</div>
<!-- #enddocregion add-hero -->
<div *ngIf="selectedHero">
<h2>
{{selectedHero.name | uppercase}} is my hero

View File

@ -4,12 +4,16 @@ import { Router } from '@angular/router-deprecated';
import { Hero } from './hero';
import { HeroService } from './hero.service';
// #docregion hero-detail-component
import { HeroDetailComponent } from './hero-detail.component';
@Component({
selector: 'my-heroes',
templateUrl: 'app/heroes.component.html',
styleUrls: ['app/heroes.component.css']
styleUrls: ['app/heroes.component.css'],
directives: [HeroDetailComponent]
})
// #enddocregion hero-detail-component
export class HeroesComponent implements OnInit {
heroes: Hero[];
selectedHero: Hero;
@ -27,6 +31,7 @@ export class HeroesComponent implements OnInit {
.catch(error => this.error = error); // TODO: Display error message
}
// #docregion add
addHero() {
this.addingHero = true;
this.selectedHero = null;
@ -36,6 +41,7 @@ export class HeroesComponent implements OnInit {
this.addingHero = false;
if (savedHero) { this.getHeroes(); }
}
// #enddocregion add
// #docregion delete
delete(hero: Hero, event: any) {

View File

@ -1,51 +1,22 @@
include ../_util-fns
:marked
# Http
# Getting and Saving Data with HTTP
Our application has become a huge success and our stakeholders have expanded the vision to include integration with a hero api.
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.
The current solution limits us to a fixed set of heroes, but integration with a web server api will make our application much more flexible. We will also be able to add, edit and delete heroes.
In this chapter we will connect our Angular 2 services to make http calls to our new api.
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).
.l-main-section
:marked
## Where We Left Off
Before we continue with our Tour of Heroes, lets verify that we have the following structure after adding our hero service
and hero detail component. If not, well need to go back and follow the previous chapters.
In the [previous chapter](toh-pt5.html), we learned to navigate between the dashboard and the fixed heroes list, editing a selected hero along the way.
That's our starting point for this chapter.
.filetree
.file angular2-tour-of-heroes
.children
.file app
.children
.file app.component.ts
.file app.component.css
.file dashboard.component.css
.file dashboard.component.html
.file dashboard.component.ts
.file hero.ts
.file hero-detail.component.css
.file hero-detail.component.html
.file hero-detail.component.ts
.file hero.service.ts
.file heroes.component.css
.file heroes.component.html
.file heroes.component.ts
.file main.ts
.file mock-heroes.ts
.file node_modules ...
.file typings ...
.file index.html
.file package.json
.file styles.css
.file systemjs.config.json
.file tsconfig.json
.file typings.json
:marked
### Keep the app transpiling and running
Open a terminal/console window and enter the following command to
start the TypeScript compiler, start the server, and watch for changes:
@ -243,9 +214,10 @@ code-example(format="." language="bash").
:marked
## Updating Components
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.
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
### 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.
+makeExample('toh-6/ts/app/hero-detail.component.ts', 'ngOnInit', 'app/hero-detail.component.ts (ngOnInit)')(format=".")
@ -267,23 +239,63 @@ code-example(format="." language="bash").
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 <a href="/docs/ts/latest/cookbook/component-communication.html#!#child-to-parent">Component Interaction Cookbook</a>
:marked
Here is `HeroDetailComponent` with the added save button.
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
### Delete
### Add/Delete in the *HeroesComponent*
We have added the option to delete hereos from `HeroesComponent`. `HeroService` will delete the hero, but we still have to filter out the deleted hero from the list to update the view.
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.
+makeExample('toh-6/ts/app/heroes.component.ts', 'delete', 'app/heroes.component.ts (delete)')(format=".")
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.ts (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 `<li>` tag:
+makeExample('toh-6/ts/app/heroes.component.html', 'delete-hero', 'app/heroes.component.ts (delete)')(format=".")
:marked
Here is `HeroesComponent` with the delete button.
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=".")
.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 `<my-hero-detail>`
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=".")
: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`.
But the component is still responsible for updating the display.
So the *delete* method removes the deleted hero from the list.
:marked
### Let's see it
Here are the fruits of labor in action:
figure.image-display
img(src='/resources/images/devguide/toh/heroes-list-delete-button.png' alt="Heroes List With Delete Button")
img(src='/resources/images/devguide/toh/toh-http.anim.gif' alt="Heroes List Editting w/ HTTP")
:marked
### Review the App Structure

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB