diff --git a/app/app.module.ts b/app/app.module.ts index 627ef1c..ccbfb20 100644 --- a/app/app.module.ts +++ b/app/app.module.ts @@ -1,3 +1,5 @@ +import "./rxjs-extensions"; + import { NgModule } from "@angular/core"; import { BrowserModule } from "@angular/platform-browser"; import { FormsModule } from "@angular/forms"; @@ -12,6 +14,7 @@ import { AppComponent } from "./app.component"; import { DucksComponent } from "./ducks.component"; import { DuckDetailComponent } from "./duck-detail.component"; import { DashboardComponent } from "./dashboard.component"; +import { DuckSearchComponent } from "./duck-search.component"; import { DuckService } from "./duck.service"; @@ -27,6 +30,7 @@ import { DuckService } from "./duck.service"; AppComponent, DucksComponent, DuckDetailComponent, + DuckSearchComponent, DashboardComponent ], providers: [ DuckService ], diff --git a/app/dashboard.component.html b/app/dashboard.component.html index 5071720..89ac14c 100644 --- a/app/dashboard.component.html +++ b/app/dashboard.component.html @@ -1,3 +1,4 @@
{{ duck.color }}
+ diff --git a/app/duck-search.component.html b/app/duck-search.component.html new file mode 100644 index 0000000..dc408d7 --- /dev/null +++ b/app/duck-search.component.html @@ -0,0 +1,11 @@ +
+

Duck search

+ +
+
+ {{ duck.color }} +
+
+
diff --git a/app/duck-search.component.ts b/app/duck-search.component.ts new file mode 100644 index 0000000..6771cdb --- /dev/null +++ b/app/duck-search.component.ts @@ -0,0 +1,43 @@ +import { Component, OnInit } from "@angular/core"; +import { Router } from "@angular/router"; +import { Observable } from "rxjs/Observable"; +import { Subject } from "rxjs/Subject"; + +import { DuckSearchService } from "./duck-search.service"; +import { Duck } from "./models"; + +@Component({ + selector: "duck-search", + templateUrl: "/app/duck-search.component.html", + providers: [ DuckSearchService ] +}) +export class DuckSearchComponent implements OnInit { + ducks: Observable; + private searchTerm = new Subject(); + + constructor(private duckSearchService: DuckSearchService, + private router: Router) + {} + + search(term: string): void { + this.searchTerm.next(term); + } + + ngOnInit(): void { + this.ducks = this.searchTerm + .debounceTime(300) // wait for 300ms pause in events + .distinctUntilChanged() // ignore if next search term is same as previous + .switchMap(term => term // switch to new observable each time + ? this.duckSearchService.search(term) + : Observable.of([])) + .catch(error => { + console.log(error); + return Observable.of([]); + }); + } + + gotoDetail(duck: Duck): void { + let link = ['/detail', duck.id]; + this.router.navigate(link); + } +} diff --git a/app/duck-search.service.ts b/app/duck-search.service.ts new file mode 100644 index 0000000..736dcac --- /dev/null +++ b/app/duck-search.service.ts @@ -0,0 +1,15 @@ +import { Injectable } from "@angular/core"; +import { Http, Response } from "@angular/http"; +import { Observable } from "rxjs"; + +import { Duck } from "./models"; + +@Injectable() +export class DuckSearchService { + constructor (private http: Http) {} + + search(term: string): Observable { + return this.http.get(`app/ducks/?color=${term}`) + .map((r: Response) => r.json().data as Duck[]); + } +} diff --git a/app/rxjs-extensions.ts b/app/rxjs-extensions.ts new file mode 100644 index 0000000..2bb03c8 --- /dev/null +++ b/app/rxjs-extensions.ts @@ -0,0 +1,12 @@ +// Observable class extensions +import "rxjs/add/observable/of"; +import "rxjs/add/observable/throw"; + +// Observable operators +import "rxjs/add/operator/catch"; +import "rxjs/add/operator/debounceTime"; +import "rxjs/add/operator/distinctUntilChanged"; +import "rxjs/add/operator/do"; +import "rxjs/add/operator/filter"; +import "rxjs/add/operator/map"; +import "rxjs/add/operator/switchMap";