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

Commit 907f848

Browse files
chalinwardbell
authored andcommitted
docs(toh-6): refactoring of 'add, edit, delete heroes' (#2170)
* docs(toh-6/dart): 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. * 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. Post-Dart-review updates included. * docs(toh-6): ward tweaks
1 parent 2bd9946 commit 907f848

24 files changed

+631
-717
lines changed

public/docs/_examples/toh-6/dart/example-config.json

Whitespace-only changes.

public/docs/_examples/toh-6/dart/lib/hero_detail_component.dart

+1-22
Original file line numberDiff line numberDiff line change
@@ -3,59 +3,38 @@
33
import 'dart:async';
44
import 'dart:html';
55

6-
// #docregion import-oninit
76
import 'package:angular2/core.dart';
8-
// #enddocregion import-oninit
9-
// #docregion import-route-params
107
import 'package:angular2/router.dart';
11-
// #enddocregion import-route-params
128

139
import 'hero.dart';
14-
// #docregion import-hero-service
1510
import 'hero_service.dart';
16-
// #enddocregion import-hero-service
1711

18-
// #docregion extract-template
1912
@Component(
2013
selector: 'my-hero-detail',
21-
// #docregion template-url
2214
templateUrl: 'hero_detail_component.html',
23-
// #enddocregion template-url, v2
2415
styleUrls: const ['hero_detail_component.css']
25-
// #docregion v2
2616
)
27-
// #enddocregion extract-template
28-
// #docregion implement
2917
class HeroDetailComponent implements OnInit {
30-
// #enddocregion implement
3118
Hero hero;
32-
// #docregion ctor
3319
final HeroService _heroService;
3420
final RouteParams _routeParams;
3521

3622
HeroDetailComponent(this._heroService, this._routeParams);
37-
// #enddocregion ctor
3823

39-
// #docregion ng-oninit
4024
Future<Null> ngOnInit() async {
41-
// #docregion get-id
4225
var idString = _routeParams.get('id');
4326
var id = int.parse(idString, onError: (_) => null);
44-
// #enddocregion get-id
4527
if (id != null) hero = await (_heroService.getHero(id));
4628
}
47-
// #enddocregion ng-oninit
4829

4930
// #docregion save
5031
Future<Null> save() async {
51-
await _heroService.save(hero);
32+
await _heroService.update(hero);
5233
goBack();
5334
}
5435
// #enddocregion save
5536

56-
// #docregion go-back
5737
void goBack() {
5838
window.history.back();
5939
}
60-
// #enddocregion go-back
6140
}

public/docs/_examples/toh-6/dart/lib/hero_detail_component.html

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
<!-- #docplaster -->
21
<!-- #docregion -->
32
<div *ngIf="hero != null">
43
<h2>{{hero.name}} details!</h2>

public/docs/_examples/toh-6/dart/lib/hero_service.dart

+16-19
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,19 @@
1-
// #docregion
1+
// #docplaster
2+
// #docregion , imports
23
import 'dart:async';
34
import 'dart:convert';
45

56
import 'package:angular2/core.dart';
67
import 'package:http/http.dart';
78

89
import 'hero.dart';
10+
// #enddocregion imports
911

1012
@Injectable()
1113
class HeroService {
12-
// #docregion post
14+
// #docregion update
1315
static final _headers = {'Content-Type': 'application/json'};
14-
// #enddocregion post
16+
// #enddocregion update
1517
// #docregion getHeroes
1618
static const _heroesUrl = 'app/heroes'; // URL to web API
1719

@@ -35,25 +37,20 @@ class HeroService {
3537

3638
// #docregion extract-data
3739
dynamic _extractData(Response resp) => JSON.decode(resp.body)['data'];
38-
// #enddocregion extract-data, getHeroes
39-
40-
Future<Hero> getHero(int id) async =>
41-
(await getHeroes()).firstWhere((hero) => hero.id == id);
42-
43-
// #docregion save
44-
Future<Hero> save(dynamic heroOrName) =>
45-
heroOrName is Hero ? _put(heroOrName) : _post(heroOrName);
46-
// #enddocregion save
40+
// #enddocregion extract-data
4741

4842
// #docregion handleError
4943
Exception _handleError(dynamic e) {
5044
print(e); // for demo purposes only
5145
return new Exception('Server error; cause: $e');
5246
}
53-
// #enddocregion handleError
47+
// #enddocregion handleError, getHeroes
48+
49+
Future<Hero> getHero(int id) async =>
50+
(await getHeroes()).firstWhere((hero) => hero.id == id);
5451

55-
// #docregion post
56-
Future<Hero> _post(String name) async {
52+
// #docregion create
53+
Future<Hero> create(String name) async {
5754
try {
5855
final response = await _http.post(_heroesUrl,
5956
headers: _headers, body: JSON.encode({'name': name}));
@@ -62,10 +59,10 @@ class HeroService {
6259
throw _handleError(e);
6360
}
6461
}
65-
// #enddocregion post
62+
// #enddocregion create
63+
// #docregion update
6664

67-
// #docregion put
68-
Future<Hero> _put(Hero hero) async {
65+
Future<Hero> update(Hero hero) async {
6966
try {
7067
var url = '$_heroesUrl/${hero.id}';
7168
final response =
@@ -75,7 +72,7 @@ class HeroService {
7572
throw _handleError(e);
7673
}
7774
}
78-
// #enddocregion put
75+
// #enddocregion update
7976

8077
// #docregion delete
8178
Future<Null> delete(int id) async {

public/docs/_examples/toh-6/dart/lib/heroes_component.css

+3-2
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/dart/lib/heroes_component.dart

+18-29
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// #docplaster
21
// #docregion
32
import 'dart:async';
43

@@ -15,44 +14,34 @@ import 'hero_service.dart';
1514
styleUrls: const ['heroes_component.css'],
1615
directives: const [HeroDetailComponent])
1716
class HeroesComponent implements OnInit {
18-
final Router _router;
19-
final HeroService _heroService;
2017
List<Hero> heroes;
2118
Hero selectedHero;
22-
// #docregion error
23-
String errorMessage;
24-
// #enddocregion error
19+
20+
final HeroService _heroService;
21+
final Router _router;
2522

2623
HeroesComponent(this._heroService, this._router);
2724

28-
// #docregion addHero
29-
Future<Null> addHero(String name) async {
30-
name = name.trim();
31-
if (name.isEmpty) return;
32-
try {
33-
heroes.add(await _heroService.save(name));
34-
} catch (e) {
35-
errorMessage = e.toString();
36-
}
25+
Future<Null> getHeroes() async {
26+
heroes = await _heroService.getHeroes();
3727
}
38-
// #enddocregion addHero
3928

40-
// #docregion deleteHero
41-
Future<Null> deleteHero(int id, event) async {
42-
try {
43-
event.stopPropagation();
44-
await _heroService.delete(id);
45-
heroes.removeWhere((hero) => hero.id == id);
46-
if (selectedHero?.id == id) selectedHero = null;
47-
} catch (e) {
48-
errorMessage = e.toString();
49-
}
29+
// #docregion add
30+
Future<Null> add(String name) async {
31+
name = name.trim();
32+
if (name.isEmpty) return;
33+
heroes.add(await _heroService.create(name));
34+
selectedHero = null;
5035
}
51-
// #enddocregion deleteHero
36+
// #enddocregion add
5237

53-
Future<Null> getHeroes() async {
54-
heroes = await _heroService.getHeroes();
38+
// #docregion delete
39+
Future<Null> delete(Hero hero) async {
40+
await _heroService.delete(hero.id);
41+
heroes.remove(hero);
42+
if (selectedHero == hero) selectedHero = null;
5543
}
44+
// #enddocregion delete
5645

5746
void ngOnInit() {
5847
getHeroes();
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,30 @@
11
<!-- #docplaster -->
22
<!-- #docregion -->
33
<h2>My Heroes</h2>
4-
<!-- #docregion add-and-error -->
5-
<div class="error" *ngIf="errorMessage != null">{{errorMessage}}</div>
4+
<!-- #docregion add -->
65
<div>
7-
Name: <input #newHeroName />
8-
<button (click)="addHero(newHeroName.value); newHeroName.value=''">
9-
Add New Hero
6+
<label>Hero name:</label> <input #heroName />
7+
<button (click)="add(heroName.value); heroName.value=''">
8+
Add
109
</button>
1110
</div>
12-
<!-- #enddocregion add-and-error -->
11+
<!-- #enddocregion add -->
1312
<ul class="heroes">
14-
<li *ngFor="let hero of heroes"
15-
[class.selected]="hero === selectedHero"
16-
(click)="onSelect(hero)">
17-
<span class="badge">{{hero.id}}</span> {{hero.name}}
13+
<!-- #docregion li-element -->
14+
<li *ngFor="let hero of heroes" (click)="onSelect(hero)"
15+
[class.selected]="hero === selectedHero">
16+
<span class="badge">{{hero.id}}</span>
17+
<span>{{hero.name}}</span>
1818
<!-- #docregion delete -->
19-
<button class="delete-button" (click)="deleteHero(hero.id, $event)">x</button>
19+
<button class="delete"
20+
(click)="delete(hero); $event.stopPropagation()">x</button>
2021
<!-- #enddocregion delete -->
2122
</li>
23+
<!-- #enddocregion li-element -->
2224
</ul>
23-
<!-- #docregion mini-detail -->
2425
<div *ngIf="selectedHero != null">
2526
<h2>
26-
<!-- #docregion pipe -->
2727
{{selectedHero.name | uppercase}} is my hero
28-
<!-- #enddocregion pipe -->
2928
</h2>
3029
<button (click)="gotoDetail()">View Details</button>
3130
</div>

public/docs/_examples/toh-6/dart/lib/in_memory_data_service.dart

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
// #docregion
1+
// #docregion , init
22
import 'dart:async';
33
import 'dart:convert';
44
import 'dart:math';
55

6-
// #docregion init
76
import 'package:angular2/core.dart';
87
import 'package:http/http.dart';
98
import 'package:http/testing.dart';
@@ -26,7 +25,6 @@ class InMemoryDataService extends MockClient {
2625
];
2726
static final List<Hero> _heroesDb =
2827
_initialHeroes.map((json) => new Hero.fromJson(json)).toList();
29-
// #enddocregion init
3028
static int _nextId = _heroesDb.map((hero) => hero.id).reduce(max) + 1;
3129

3230
static Future<Response> _handler(Request request) async {
@@ -37,6 +35,7 @@ class InMemoryDataService extends MockClient {
3735
final regExp = new RegExp(prefix, caseSensitive: false);
3836
data = _heroesDb.where((hero) => hero.name.contains(regExp)).toList();
3937
break;
38+
// #enddocregion init-disabled
4039
case 'POST':
4140
var name = JSON.decode(request.body)['name'];
4241
var newHero = new Hero(_nextId++, name);
@@ -54,6 +53,7 @@ class InMemoryDataService extends MockClient {
5453
_heroesDb.removeWhere((hero) => hero.id == id);
5554
// No data, so leave it as null.
5655
break;
56+
// #docregion init-disabled
5757
default:
5858
throw 'Unimplemented HTTP method ${request.method}';
5959
}
@@ -62,5 +62,4 @@ class InMemoryDataService extends MockClient {
6262
}
6363

6464
InMemoryDataService() : super(_handler);
65-
// #docregion init
6665
}

public/docs/_examples/toh-6/dart/web/main.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import 'package:angular2/core.dart';
44
import 'package:angular2/platform/browser.dart';
55
import 'package:angular2_tour_of_heroes/app_component.dart';
66
// #enddocregion v1
7-
import 'package:http/http.dart';
87
import 'package:angular2_tour_of_heroes/in_memory_data_service.dart';
8+
import 'package:http/http.dart';
99

1010
void main() {
1111
bootstrap(AppComponent,

0 commit comments

Comments
 (0)