extends ../../../ts/_cache/tutorial/toh-pt6.jade block includes include ../_util-fns - var _Http = 'BrowserClient'; - var _Angular_Http = 'Dart BrowserClient' - var _httpUrl = 'https://pub.dartlang.org/packages/http' - var _Angular_http_library = 'Dart http package' - var _HttpModule = 'BrowserClient' - var _JSON_stringify = 'JSON.encode' block start-server-and-watch :marked ### Keep the app compiling and running Open a terminal/console window. Start the Dart compiler, watch for changes, and start our server by entering the command: code-example(language="bash"). pub serve block http-library :marked We'll be using the !{_Angular_http_library}'s `BrowserClient` class to communicate with a server. ### Pubspec updates Update package dependencies by adding the `stream_transformers` and !{_Angular_http_library}s. We also need to add a `resolved_identifiers` entry, to inform the [angular2 transformer][ng2x] that we'll be using `BrowserClient`. (For an explanation of why this extra configuration is needed, see the [HTTP client chapter][guide-http].) We'll also need to use `Client` from http, so let's add that now as well. Update `pubspec.yaml` to look like this (additions are highlighted): [guide-http]: ../guide/server-communication.html#!#http-providers [ng2x]: https://github.com/angular/angular/wiki/Angular-2-Dart-Transformer - var stylePattern = { pnk: /(http.*|stream.*|resolved_identifiers:|Browser.*|Client.*)/gm }; +makeExcerpt('pubspec.yaml', 'additions', null, stylePattern) block http-providers :marked Before our app can use `#{_Http}`, we have to register it as a service provider. We should be able to access `!{_Http}` services from anywhere in the application. So we register it in the `bootstrap` call where we launch the application and its root `AppComponent`. +makeExcerpt('app/main.ts','v1') :marked Notice that we supply `!{_HttpModule}` in a list, as the second parameter to the `bootstrap` method. This has the same effect as the `providers` list in `@Component` annotation. block backend :marked We want to replace `BrowserClient`, the service that talks to the remote server, with the in-memory web API service. Our in-memory web API service, shown below, is implemented using the `http` library `MockClient` class. All `http` client implementations share a common `Client` interface, so we'll have our app use the `Client` type so that we can freely switch between implementations. block dont-be-distracted-by-backend-subst //- No backend substitution but we do need to comment on the changes to Hero. :marked As is common for web API services, our mock in-memory service will be encoding and decoding heroes in JSON format, so we enhance the `Hero` class with these capabilities: +makeExample('lib/hero.dart') block get-heroes-details :marked To get the list of heroes, we first make an asynchronous call to `http.get()`. Then we use the `_extractData` helper method to decode the response body. block observables-section-intro :marked Recall that `HeroService.getHeroes()` awaits for an `http.get()` response and yields a _Future_ `List`, which is fine when we are only interested in a single result. block search-criteria-intro :marked A [StreamController][], as its name implies, is a controller for a [Stream][] that allows us to manipulate the underlying stream by adding data to it, for example. In our sample, the underlying stream of strings (`_searchTerms.stream`) represents the hero name search patterns entered by the user. Each call to `search` puts a new string into the stream by calling `add` over the controller. [Stream]: https://api.dartlang.org/stable/dart-async/Stream-class.html [StreamController]: https://api.dartlang.org/stable/dart-async/StreamController-class.html block observable-transformers :marked Fortunately, there are stream transformers that will help us reduce the request flow. We'll make fewer calls to the `HeroSearchService` and still get timely results. Here's how: * `transform(new Debounce(... 300)))` waits until the flow of search terms pauses for 300 milliseconds before passing along the latest string. We'll never make requests more frequently than 300ms. * `distinct()` ensures that we only send a request if a search term has changed. There's no point in repeating a request for the same search term. * `transform(new FlatMapLatest(...))` applies a map-like transformer that (1) calls our search service for each search term that makes it through the debounce and distinct gauntlet and (2) returns only the most recent search service result, discarding any previous results. * `handleError()` handles errors. Our simple example prints the error to the console; a real life application should do better. block filetree .filetree .file angular2_tour_of_heroes .children .file lib .children .file app_component.css .file app_component.dart .file dashboard_component.css .file dashboard_component.dart .file dashboard_component.html .file hero.dart .file hero_detail_component.css .file hero_detail_component.dart .file hero_detail_component.html .file hero_search_component.css (new) .file hero_search_component.dart (new) .file hero_search_component.html (new) .file hero_search_service.dart (new) .file hero_service.dart .file heroes_component.css .file heroes_component.dart .file heroes_component.html .file in_memory_data_service.dart (new) .file web .children .file main.dart .file index.html .file styles.css .file pubspec.yaml block file-summary +makeTabs( `toh-6/dart/lib/dashboard_component.dart, toh-6/dart/lib/dashboard_component.html, toh-6/dart/lib/hero.dart, toh-6/dart/lib/hero_detail_component.dart, toh-6/dart/lib/hero_detail_component.html, toh-6/dart/lib/hero_service.dart, toh-6/dart/lib/heroes_component.css, toh-6/dart/lib/heroes_component.dart, toh-6/dart/lib/in_memory_data_service.dart`, ',,,,,,,,', `lib/dashboard_component.dart, lib/dashboard_component.html, lib/hero.dart, lib/hero_detail_component.dart, lib/hero_detail_component.html, lib/hero_service.dart, lib/heroes_component.css, lib/heroes_component.dart, lib/in_memory_data_service.dart`) +makeTabs( `toh-6/dart/lib/hero_search_component.css, toh-6/dart/lib/hero_search_component.dart, toh-6/dart/lib/hero_search_component.html, toh-6/dart/lib/hero_search_service.dart`, null, `lib/hero_search_component.css, lib/hero_search_component.dart, lib/hero_search_component.html, lib/hero_search_service.dart`) +makeTabs( `toh-6/dart/pubspec.yaml, toh-6/dart/web/main.dart`, null, `pubspec.yaml, web/main.dart`)