Skip to content
This repository was archived by the owner on Dec 4, 2017. It is now read-only.

Commit 5a7b10a

Browse files
committed
docs(toh-6/ts): refactoring of 'add, edit, delete heroes'
Refactoring of "add, edit, delete heroes" section of toh-6 from one big bottom-up step into small independent feature slices, where the user achieves a "milesone" (i.e., can run the full app) after each feature section. The section rewrite is shorter and offers a better UX. Other simplifications: - Error handling is consistent: in the hero service we log to the console, everwhere else we just let errors bubble up. - Hero service methods renamed based on function (create, update) rather then lower-level implementation (post, put). - @output properties have been eliminated (since they weren't explained). E2E tests now pass on both the TS and Dart sides.
1 parent 857f6cc commit 5a7b10a

File tree

8 files changed

+402
-430
lines changed

8 files changed

+402
-430
lines changed

public/docs/_examples/toh-6/e2e-spec.ts

Lines changed: 234 additions & 197 deletions
Large diffs are not rendered by default.

public/docs/_examples/toh-6/ts/app/hero-detail.component.html

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
<!-- #docplaster -->
21
<!-- #docregion -->
32
<div *ngIf="hero">
43
<h2>{{hero.name}} details!</h2>
Lines changed: 11 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
// #docplaster
2-
// #docregion, variables-imports
3-
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
4-
5-
// #enddocregion variables-imports
1+
// #docregion
2+
import { Component, OnInit } from '@angular/core';
63
import { ActivatedRoute, Params } from '@angular/router';
74

85
import { Hero } from './hero';
@@ -13,50 +10,30 @@ import { HeroService } from './hero.service';
1310
templateUrl: 'app/hero-detail.component.html',
1411
styleUrls: ['app/hero-detail.component.css']
1512
})
16-
// #docregion variables-imports
1713
export class HeroDetailComponent implements OnInit {
18-
@Input() hero: Hero;
19-
@Output() close = new EventEmitter();
20-
error: any;
21-
navigated = false; // true if navigated here
22-
// #enddocregion variables-imports
14+
hero: Hero;
2315

2416
constructor(
2517
private heroService: HeroService,
2618
private route: ActivatedRoute) {
2719
}
2820

29-
// #docregion ngOnInit
3021
ngOnInit(): void {
3122
this.route.params.forEach((params: Params) => {
32-
if (params['id'] !== undefined) {
33-
let id = +params['id'];
34-
this.navigated = true;
35-
this.heroService.getHero(id)
36-
.then(hero => this.hero = hero);
37-
} else {
38-
this.navigated = false;
39-
this.hero = new Hero();
40-
}
23+
let id = +params['id'];
24+
this.heroService.getHero(id)
25+
.then(hero => this.hero = hero);
4126
});
4227
}
43-
// #enddocregion ngOnInit
4428

4529
// #docregion save
4630
save(): void {
47-
this.heroService
48-
.save(this.hero)
49-
.then(hero => {
50-
this.hero = hero; // saved hero, w/ id if new
51-
this.goBack(hero);
52-
})
53-
.catch(error => this.error = error); // TODO: Display error message
31+
this.heroService.update(this.hero)
32+
.then(this.goBack);
5433
}
5534
// #enddocregion save
56-
// #docregion goBack
57-
goBack(savedHero: Hero = null): void {
58-
this.close.emit(savedHero);
59-
if (this.navigated) { window.history.back(); }
35+
36+
goBack(): void {
37+
window.history.back();
6038
}
61-
// #enddocregion goBack
6239
}

public/docs/_examples/toh-6/ts/app/hero.service.ts

Lines changed: 28 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
// #docplaster
2-
// #docregion
2+
// #docregion , imports
33
import { Injectable } from '@angular/core';
4-
import { Headers, Http, Response } from '@angular/http';
4+
import { Headers, Http } from '@angular/http';
55

66
// #docregion rxjs
77
import 'rxjs/add/operator/toPromise';
88
// #enddocregion rxjs
99

1010
import { Hero } from './hero';
11+
// #enddocregion imports
1112

1213
@Injectable()
1314
export class HeroService {
1415

16+
// #docregion update
17+
private headers = new Headers({'Content-Type': 'application/json'});
18+
// #enddocregion update
1519
// #docregion getHeroes
1620
private heroesUrl = 'app/heroes'; // URL to web api
1721

@@ -36,62 +40,40 @@ export class HeroService {
3640
.then(heroes => heroes.find(hero => hero.id === id));
3741
}
3842

39-
// #docregion save
40-
save(hero: Hero): Promise<Hero> {
41-
if (hero.id) {
42-
return this.put(hero);
43-
}
44-
return this.post(hero);
45-
}
46-
// #enddocregion save
47-
4843
// #docregion delete
49-
delete(hero: Hero): Promise<Response> {
50-
let headers = new Headers();
51-
headers.append('Content-Type', 'application/json');
52-
53-
let url = `${this.heroesUrl}/${hero.id}`;
54-
55-
return this.http
56-
.delete(url, {headers: headers})
57-
.toPromise()
58-
.catch(this.handleError);
44+
delete(id: number): Promise<void> {
45+
let url = `${this.heroesUrl}/${id}`;
46+
return this.http.delete(url, {headers: this.headers})
47+
.toPromise()
48+
.then(() => null)
49+
.catch(this.handleError);
5950
}
6051
// #enddocregion delete
6152

62-
// #docregion post
63-
// Add new Hero
64-
private post(hero: Hero): Promise<Hero> {
65-
let headers = new Headers({
66-
'Content-Type': 'application/json'});
67-
53+
// #docregion create
54+
create(name: string): Promise<Hero> {
6855
return this.http
69-
.post(this.heroesUrl, JSON.stringify(hero), {headers: headers})
70-
.toPromise()
71-
.then(res => res.json().data)
72-
.catch(this.handleError);
56+
.post(this.heroesUrl, JSON.stringify({name: name}), {headers: this.headers})
57+
.toPromise()
58+
.then(res => res.json().data)
59+
.catch(this.handleError);
7360
}
74-
// #enddocregion post
75-
76-
// #docregion put
77-
// Update existing Hero
78-
private put(hero: Hero): Promise<Hero> {
79-
let headers = new Headers();
80-
headers.append('Content-Type', 'application/json');
81-
82-
let url = `${this.heroesUrl}/${hero.id}`;
61+
// #enddocregion create
62+
// #docregion update
8363

64+
update(hero: Hero): Promise<Hero> {
65+
const url = `${this.heroesUrl}/${hero.id}`;
8466
return this.http
85-
.put(url, JSON.stringify(hero), {headers: headers})
86-
.toPromise()
87-
.then(() => hero)
88-
.catch(this.handleError);
67+
.put(url, JSON.stringify(hero), {headers: this.headers})
68+
.toPromise()
69+
.then(() => hero)
70+
.catch(this.handleError);
8971
}
90-
// #enddocregion put
72+
// #enddocregion put, update
9173

9274
// #docregion handleError
9375
private handleError(error: any): Promise<any> {
94-
console.error('An error occurred', error);
76+
console.error('An error occurred', error); // for demo purposes only
9577
return Promise.reject(error.message || error);
9678
}
9779
// #enddocregion handleError

public/docs/_examples/toh-6/ts/app/heroes.component.css

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,10 @@ button:hover {
5959
background-color: #cfd8dc;
6060
}
6161
/* #docregion additions */
62-
.error {color:red;}
63-
button.delete-button{
62+
button.delete {
6463
float:right;
64+
margin-top: 2px;
65+
margin-right: .8em;
6566
background-color: gray !important;
6667
color:white;
6768
}

public/docs/_examples/toh-6/ts/app/heroes.component.ts

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,65 +4,55 @@ import { Router } from '@angular/router';
44

55
import { Hero } from './hero';
66
import { HeroService } from './hero.service';
7-
// #docregion hero-detail-component
87

98
@Component({
109
selector: 'my-heroes',
1110
templateUrl: 'app/heroes.component.html',
1211
styleUrls: ['app/heroes.component.css']
1312
})
14-
// #enddocregion hero-detail-component
1513
export class HeroesComponent implements OnInit {
1614
heroes: Hero[];
1715
selectedHero: Hero;
18-
addingHero = false;
19-
// #docregion error
20-
error: any;
21-
// #enddocregion error
2216

2317
constructor(
24-
private router: Router,
25-
private heroService: HeroService) { }
18+
private heroService: HeroService,
19+
private router: Router) { }
2620

2721
getHeroes(): void {
2822
this.heroService
2923
.getHeroes()
30-
.then(heroes => this.heroes = heroes)
31-
.catch(error => this.error = error);
24+
.then(heroes => this.heroes = heroes);
3225
}
3326

34-
// #docregion addHero
35-
addHero(): void {
36-
this.addingHero = true;
37-
this.selectedHero = null;
27+
// #docregion add
28+
add(name: string): void {
29+
name = name.trim();
30+
if (!name) { return; }
31+
this.heroService.create(name)
32+
.then(hero => {
33+
this.heroes.push(hero);
34+
this.selectedHero = null;
35+
});
3836
}
37+
// #enddocregion add
3938

40-
close(savedHero: Hero): void {
41-
this.addingHero = false;
42-
if (savedHero) { this.getHeroes(); }
43-
}
44-
// #enddocregion addHero
45-
46-
// #docregion deleteHero
47-
deleteHero(hero: Hero, event: any): void {
48-
event.stopPropagation();
39+
// #docregion delete
40+
delete(hero: Hero): void {
4941
this.heroService
50-
.delete(hero)
51-
.then(res => {
42+
.delete(hero.id)
43+
.then(() => {
5244
this.heroes = this.heroes.filter(h => h !== hero);
5345
if (this.selectedHero === hero) { this.selectedHero = null; }
54-
})
55-
.catch(error => this.error = error);
46+
});
5647
}
57-
// #enddocregion deleteHero
48+
// #enddocregion delete
5849

5950
ngOnInit(): void {
6051
this.getHeroes();
6152
}
6253

6354
onSelect(hero: Hero): void {
6455
this.selectedHero = hero;
65-
this.addingHero = false;
6656
}
6757

6858
gotoDetail(): void {

public/docs/ts/latest/tutorial/_data.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@
3131
"nextable": true
3232
},
3333
"toh-pt6": {
34-
"title": "Http",
35-
"intro": "We convert our service and components to use Http",
34+
"title": "HTTP",
35+
"intro": "We convert our service and components to use HTTP",
3636
"nextable": true
3737
}
38-
}
38+
}

0 commit comments

Comments
 (0)