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

Commit f50dff8

Browse files
thelgevoldwardbell
authored andcommitted
docs(toh-pt6): add observables to HTTP tutorial chapter
closes #1528
1 parent f056a2d commit f50dff8

File tree

12 files changed

+306
-7
lines changed

12 files changed

+306
-7
lines changed

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

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,31 @@ describe('TOH Http Chapter', function () {
2323

2424
addButton: element.all(by.buttonText('Add New Hero')).get(0),
2525

26-
heroDetail: element(by.css('my-app my-hero-detail'))
26+
heroDetail: element(by.css('my-app my-hero-detail')),
27+
28+
searchBox: element(by.css('#search-box')),
29+
searchResults: element.all(by.css('.search-result'))
2730
};
2831
}
2932

33+
it('should search for hero and navigate to details view', function() {
34+
let page = getPageStruct();
35+
36+
return sendKeys(page.searchBox, 'Magneta').then(function () {
37+
expect(page.searchResults.count()).toBe(1);
38+
let hero = page.searchResults.get(0);
39+
return hero.click();
40+
})
41+
.then(function() {
42+
browser.waitForAngular();
43+
let inputEle = page.heroDetail.element(by.css('input'));
44+
return inputEle.getAttribute('value');
45+
})
46+
.then(function(value) {
47+
expect(value).toBe('Magneta');
48+
});
49+
});
50+
3051
it('should be able to add a hero from the "Heroes" view', function(){
3152
let page = getPageStruct();
3253
let heroCount: webdriver.promise.Promise<number>;

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ import { Component } from '@angular/core';
44
import { ROUTER_DIRECTIVES } from '@angular/router';
55

66
import { HeroService } from './hero.service';
7+
// #docregion rxjs-extensions
8+
import './rxjs-extensions';
9+
// #enddocregion rxjs-extensions
710

811
@Component({
912
selector: 'my-app',

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,5 @@ <h4>{{hero.name}}</h4>
99
</div>
1010
</div>
1111
</div>
12+
<hero-search></hero-search>
13+

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import { Router } from '@angular/router';
55

66
import { Hero } from './hero';
77
import { HeroService } from './hero.service';
8+
import { HeroSearchComponent } from './hero-search.component';
89

910
@Component({
1011
selector: 'my-dashboard',
1112
templateUrl: 'app/dashboard.component.html',
12-
styleUrls: ['app/dashboard.component.css']
13+
styleUrls: ['app/dashboard.component.css'],
14+
directives: [HeroSearchComponent]
1315
})
1416
export class DashboardComponent implements OnInit {
1517

Lines changed: 11 additions & 0 deletions
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.next(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>
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
// #docplaster
2+
// #docregion
3+
import { Component, OnInit } from '@angular/core';
4+
import { Router } from '@angular/router';
5+
import { Observable } from 'rxjs/Observable';
6+
import { Subject } from 'rxjs/Subject';
7+
8+
import { HeroSearchService } from './hero-search.service';
9+
import { Hero } from './hero';
10+
11+
@Component({
12+
selector: 'hero-search',
13+
templateUrl: 'app/hero-search.component.html',
14+
providers: [HeroSearchService]
15+
})
16+
export class HeroSearchComponent implements OnInit {
17+
// #docregion subject
18+
search = new Subject<string>();
19+
// #enddocregion subject
20+
// #docregion search
21+
heroes: Observable<Hero>;
22+
// #enddocregion search
23+
24+
constructor(
25+
private heroSearchService: HeroSearchService,
26+
private router: Router) {}
27+
28+
29+
// #docregion search
30+
ngOnInit() {
31+
this.heroes = this.search
32+
.asObservable() // "cast" as Observable
33+
.debounceTime(300) // wait for 300ms pause in events
34+
.distinctUntilChanged() // ignore if next search term is same as previous
35+
.switchMap(term => term // switch to new observable each time
36+
// return the http search observable
37+
? this.heroSearchService.search(term)
38+
// or the observable of empty heroes if no search term
39+
: Observable.of<Hero[]>([]))
40+
41+
.catch(error => {
42+
// Todo: real error handling
43+
console.log(error);
44+
return Observable.throw(error);
45+
});
46+
}
47+
// #enddocregion search
48+
49+
gotoDetail(hero: Hero) {
50+
let link = ['/detail', hero.id];
51+
this.router.navigate(link);
52+
}
53+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// #docregion
2+
import { Injectable } from '@angular/core';
3+
import { Http, Response } from '@angular/http';
4+
5+
import { Hero } from './hero';
6+
7+
@Injectable()
8+
export class HeroSearchService {
9+
10+
constructor(private http: Http) {}
11+
12+
// #docregion observable-search
13+
search(term: string) {
14+
return this.http
15+
.get(`app/heroes/?name=${term}+`)
16+
.map((r: Response) => r.json().data as Hero[]);
17+
}
18+
// #enddocregion observable-search
19+
}

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ export class HeroService {
1717

1818
constructor(private http: Http) { }
1919

20-
getHeroes(): Promise<Hero[]> {
20+
getHeroes() {
2121
return this.http.get(this.heroesUrl)
2222
// #docregion to-promise
2323
.toPromise()
2424
// #enddocregion to-promise
2525
// #docregion to-data
26-
.then(response => response.json().data)
26+
.then(response => response.json().data as Hero[])
2727
// #enddocregion to-data
2828
// #docregion catch
2929
.catch(this.handleError);
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
// #docregion
2+
// Observable class extensions
3+
import 'rxjs/add/observable/of';
4+
import 'rxjs/add/observable/throw';
5+
6+
// Observable operators
7+
import 'rxjs/add/operator/catch';
8+
import 'rxjs/add/operator/debounceTime';
9+
import 'rxjs/add/operator/distinctUntilChanged';
10+
import 'rxjs/add/operator/do';
11+
import 'rxjs/add/operator/filter';
12+
import 'rxjs/add/operator/map';
13+
import 'rxjs/add/operator/switchMap';

public/docs/_examples/toh-6/ts/sample.css

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,20 @@ button.delete-button{
55
background-color: gray !important;
66
color:white;
77
}
8+
9+
.search-result{
10+
border-bottom: 1px solid gray;
11+
border-left: 1px solid gray;
12+
border-right: 1px solid gray;
13+
width:195px;
14+
height: 20px;
15+
padding: 5px;
16+
background-color: white;
17+
cursor: pointer;
18+
}
19+
20+
#search-box{
21+
width: 200px;
22+
height: 20px;
23+
}
24+

0 commit comments

Comments
 (0)