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

Commit 8a6c5b5

Browse files
chalinkwalrath
authored andcommitted
docs(toh-6): add hero search to Dart; minor edits to TS (#2018)
* docs(toh-6/dart): add hero search Fixes #1924. * docs(toh-6/ts): minor updates * post-review updates * post-review updates
1 parent a49ecc7 commit 8a6c5b5

15 files changed

+321
-134
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,36 @@
1-
// #docplaster
2-
// #docregion
1+
// #docregion , search
32
import 'dart:async';
43

54
import 'package:angular2/core.dart';
6-
// #docregion import-router
75
import 'package:angular2/router.dart';
8-
// #enddocregion import-router
96

107
import 'hero.dart';
118
import 'hero_service.dart';
9+
import 'hero_search_component.dart';
1210

1311
@Component(
1412
selector: 'my-dashboard',
15-
// #docregion template-url
1613
templateUrl: 'dashboard_component.html',
17-
// #enddocregion template-url
18-
// #docregion css
19-
styleUrls: const ['dashboard_component.css']
20-
// #enddocregion css
21-
)
22-
// #docregion component
14+
styleUrls: const ['dashboard_component.css'],
15+
directives: const [HeroSearchComponent])
16+
// #enddocregion search
2317
class DashboardComponent implements OnInit {
2418
List<Hero> heroes;
2519

26-
// #docregion ctor
2720
final Router _router;
2821
final HeroService _heroService;
2922

3023
DashboardComponent(this._heroService, this._router);
3124

32-
// #enddocregion ctor
33-
3425
Future<Null> ngOnInit() async {
3526
heroes = (await _heroService.getHeroes()).skip(1).take(4).toList();
3627
}
3728

38-
// #docregion goto-detail
3929
void gotoDetail(Hero hero) {
4030
var link = [
4131
'HeroDetail',
4232
{'id': hero.id.toString()}
4333
];
4434
_router.navigate(link);
4535
}
46-
// #enddocregion goto-detail
4736
}
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
<!-- #docregion -->
22
<h3>Top Heroes</h3>
33
<div class="grid grid-pad">
4-
<!-- #docregion click -->
5-
<div *ngFor="let hero of heroes" (click)="gotoDetail(hero)" class="col-1-4" >
6-
<!-- #enddocregion click -->
4+
<div *ngFor="let hero of heroes" (click)="gotoDetail(hero)" class="col-1-4">
75
<div class="module hero">
86
<h4>{{hero.name}}</h4>
97
</div>
108
</div>
119
</div>
10+
<hero-search></hero-search>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
/* #docregion */
2+
.search-result {
3+
border-bottom: 1px solid gray;
4+
border-left: 1px solid gray;
5+
border-right: 1px solid gray;
6+
width:195px;
7+
height: 20px;
8+
padding: 5px;
9+
background-color: white;
10+
cursor: pointer;
11+
}
12+
#search-box {
13+
width: 200px;
14+
height: 20px;
15+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
// #docplaster
2+
// #docregion
3+
import 'dart:async';
4+
5+
import 'package:angular2/core.dart';
6+
import 'package:angular2/router.dart';
7+
import 'package:stream_transformers/stream_transformers.dart';
8+
9+
import 'hero_search_service.dart';
10+
import 'hero.dart';
11+
12+
@Component(
13+
selector: 'hero-search',
14+
templateUrl: 'hero_search_component.html',
15+
styleUrls: const ['hero_search_component.css'],
16+
providers: const [HeroSearchService])
17+
class HeroSearchComponent implements OnInit {
18+
HeroSearchService _heroSearchService;
19+
Router _router;
20+
21+
// #docregion search
22+
Stream<List<Hero>> heroes;
23+
// #enddocregion search
24+
// #docregion searchTerms
25+
StreamController<String> _searchTerms =
26+
new StreamController<String>.broadcast();
27+
// #enddocregion searchTerms
28+
29+
HeroSearchComponent(this._heroSearchService, this._router) {}
30+
// #docregion searchTerms
31+
32+
// Push a search term into the stream.
33+
void search(String term) => _searchTerms.add(term);
34+
// #enddocregion searchTerms
35+
// #docregion search
36+
37+
Future<Null> ngOnInit() async {
38+
heroes = _searchTerms.stream
39+
.transform(new Debounce(new Duration(milliseconds: 300)))
40+
.distinct()
41+
.transform(new FlatMapLatest((term) => term.isEmpty
42+
? new Stream<List<Hero>>.fromIterable([<Hero>[]])
43+
: _heroSearchService.search(term).asStream()))
44+
.handleError((e) {
45+
print(e); // for demo purposes only
46+
});
47+
}
48+
// #enddocregion search
49+
50+
void gotoDetail(Hero hero) {
51+
var link = [
52+
'HeroDetail',
53+
{'id': hero.id.toString()}
54+
];
55+
_router.navigate(link);
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!-- #docregion -->
2+
<div id="search-component">
3+
<h4>Hero Search</h4>
4+
<input #searchBox id="search-box" (keyup)="search(searchBox.value)" />
5+
<div>
6+
<div *ngFor="let hero of heroes | async"
7+
(click)="gotoDetail(hero)" class="search-result" >
8+
{{hero.name}}
9+
</div>
10+
</div>
11+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// #docregion
2+
import 'dart:async';
3+
import 'dart:convert';
4+
5+
import 'package:angular2/core.dart';
6+
import 'package:http/http.dart';
7+
8+
import 'hero.dart';
9+
10+
@Injectable()
11+
class HeroSearchService {
12+
final Client _http;
13+
14+
HeroSearchService(this._http);
15+
16+
Future<List<Hero>> search(String term) async {
17+
try {
18+
final response = await _http.get('app/heroes/?name=$term');
19+
return _extractData(response)
20+
.map((json) => new Hero.fromJson(json))
21+
.toList();
22+
} catch (e) {
23+
throw _handleError(e);
24+
}
25+
}
26+
27+
dynamic _extractData(Response resp) => JSON.decode(resp.body)['data'];
28+
29+
Exception _handleError(dynamic e) {
30+
print(e); // for demo purposes only
31+
return new Exception('Server error; cause: $e');
32+
}
33+
}

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

+8
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* #docregion */
12
.selected {
23
background-color: #CFD8DC !important;
34
color: white;
@@ -57,3 +58,10 @@ button {
5758
button:hover {
5859
background-color: #cfd8dc;
5960
}
61+
/* #docregion additions */
62+
.error {color:red;}
63+
button.delete-button {
64+
float:right;
65+
background-color: gray !important;
66+
color:white;
67+
}

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

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// #docregion
22
import 'dart:async';
33
import 'dart:convert';
4+
import 'dart:math';
45

56
// #docregion init
67
import 'package:angular2/core.dart';
@@ -23,17 +24,18 @@ class InMemoryDataService extends MockClient {
2324
{'id': 19, 'name': 'Magma'},
2425
{'id': 20, 'name': 'Tornado'}
2526
];
26-
// #enddocregion init
27-
2827
static final List<Hero> _heroesDb =
2928
_initialHeroes.map((json) => new Hero.fromJson(json)).toList();
30-
static int _nextId = 21;
29+
// #enddocregion init
30+
static int _nextId = _heroesDb.map((hero) => hero.id).reduce(max) + 1;
3131

3232
static Future<Response> _handler(Request request) async {
3333
var data;
3434
switch (request.method) {
3535
case 'GET':
36-
data = _heroesDb;
36+
String prefix = request.url.queryParameters['name'] ?? '';
37+
final regExp = new RegExp(prefix, caseSensitive: false);
38+
data = _heroesDb.where((hero) => hero.name.contains(regExp)).toList();
3739
break;
3840
case 'POST':
3941
var name = JSON.decode(request.body)['name'];

public/docs/_examples/toh-6/dart/pubspec.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ dependencies:
1313
dart_to_js_script_rewriter: ^1.0.1
1414
# #docregion additions
1515
http: ^0.11.0
16+
stream_transformers: ^0.3.0
1617
transformers:
1718
- angular2:
1819
# #enddocregion additions

public/docs/_examples/toh-6/dart/web/index.html

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
<meta name="viewport" content="width=device-width, initial-scale=1">
88

99
<link rel="stylesheet" href="styles.css">
10-
<link rel="stylesheet" href="sample.css">
1110

1211
<script defer src="main.dart" type="application/dart"></script>
1312
<script defer src="packages/browser/dart.js"></script>

public/docs/_examples/toh-6/dart/web/sample.css

-7
This file was deleted.

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

+2-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
// #docplaster
2-
// #docregion
3-
// #docregion hero-search-component
1+
// #docregion , search
42
import { Component, OnInit } from '@angular/core';
53
import { Router } from '@angular/router';
64

@@ -14,9 +12,8 @@ import { HeroSearchComponent } from './hero-search.component';
1412
styleUrls: ['app/dashboard.component.css'],
1513
directives: [HeroSearchComponent]
1614
})
17-
// #enddocregion hero-search-component
15+
// #enddocregion search
1816
export class DashboardComponent implements OnInit {
19-
2017
heroes: Hero[] = [];
2118

2219
constructor(

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class HeroSearchComponent implements OnInit {
1818
heroes: Observable<Hero[]>;
1919
// #enddocregion search
2020
// #docregion searchTerms
21-
searchTerms = new Subject<string>();
21+
private searchTerms = new Subject<string>();
2222
// #enddocregion searchTerms
2323

2424
constructor(

0 commit comments

Comments
 (0)