From 7d670272c0d71196525980ca4738cf501444fe08 Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Tue, 6 Dec 2016 12:18:35 -0800 Subject: [PATCH] docs(toh-6/dart): getHero makes HTTP get-by-id Dart follow-up to #2906 --- .../toh-6/dart/lib/hero_service.dart | 18 +++++--- .../dart/lib/in_memory_data_service.dart | 11 +++-- public/docs/ts/_cache/tutorial/toh-pt6.jade | 41 +++++++++++++------ public/docs/ts/latest/tutorial/toh-pt6.jade | 2 +- 4 files changed, 51 insertions(+), 21 deletions(-) diff --git a/public/docs/_examples/toh-6/dart/lib/hero_service.dart b/public/docs/_examples/toh-6/dart/lib/hero_service.dart index 38e8357968..08d18d69d5 100644 --- a/public/docs/_examples/toh-6/dart/lib/hero_service.dart +++ b/public/docs/_examples/toh-6/dart/lib/hero_service.dart @@ -15,7 +15,7 @@ class HeroService { static final _headers = {'Content-Type': 'application/json'}; // #enddocregion update // #docregion getHeroes - static const _heroesUrl = 'app/heroes'; // URL to web API + static const _heroesUrl = 'api/heroes'; // URL to web API final Client _http; @@ -46,8 +46,16 @@ class HeroService { } // #enddocregion handleError, getHeroes - Future getHero(int id) async => - (await getHeroes()).firstWhere((hero) => hero.id == id); + // #docregion getHero + Future getHero(int id) async { + try { + final response = await _http.get('$_heroesUrl/$id'); + return new Hero.fromJson(_extractData(response)); + } catch (e) { + throw _handleError(e); + } + } + // #enddocregion getHero // #docregion create Future create(String name) async { @@ -64,7 +72,7 @@ class HeroService { Future update(Hero hero) async { try { - var url = '$_heroesUrl/${hero.id}'; + final url = '$_heroesUrl/${hero.id}'; final response = await _http.put(url, headers: _headers, body: JSON.encode(hero)); return new Hero.fromJson(_extractData(response)); @@ -77,7 +85,7 @@ class HeroService { // #docregion delete Future delete(int id) async { try { - var url = '$_heroesUrl/$id'; + final url = '$_heroesUrl/$id'; await _http.delete(url, headers: _headers); } catch (e) { throw _handleError(e); diff --git a/public/docs/_examples/toh-6/dart/lib/in_memory_data_service.dart b/public/docs/_examples/toh-6/dart/lib/in_memory_data_service.dart index 2472a4f4a5..f17195b204 100644 --- a/public/docs/_examples/toh-6/dart/lib/in_memory_data_service.dart +++ b/public/docs/_examples/toh-6/dart/lib/in_memory_data_service.dart @@ -31,9 +31,14 @@ class InMemoryDataService extends MockClient { var data; switch (request.method) { case 'GET': - String prefix = request.url.queryParameters['name'] ?? ''; - final regExp = new RegExp(prefix, caseSensitive: false); - data = _heroesDb.where((hero) => hero.name.contains(regExp)).toList(); + final id = int.parse(request.url.pathSegments.last, onError: (_) => null); + if (id != null) { + data = _heroesDb.firstWhere((hero) => hero.id == id); // throws if no match + } else { + String prefix = request.url.queryParameters['name'] ?? ''; + final regExp = new RegExp(prefix, caseSensitive: false); + data = _heroesDb.where((hero) => hero.name.contains(regExp)).toList(); + } break; // #enddocregion init-disabled case 'POST': diff --git a/public/docs/ts/_cache/tutorial/toh-pt6.jade b/public/docs/ts/_cache/tutorial/toh-pt6.jade index 078f494a1b..46baa9c0cc 100644 --- a/public/docs/ts/_cache/tutorial/toh-pt6.jade +++ b/public/docs/ts/_cache/tutorial/toh-pt6.jade @@ -212,12 +212,32 @@ block get-heroes-details We've also decided to return a user friendly form of the error to the caller in a !{rejected_promise} so that the caller can display a proper error message to the user. - ### Unchanged `getHeroes` API + ### Get hero by id + The `HeroDetailComponent` asks the `HeroService` to fetch a single hero to edit. + + The `HeroService` currently fetches all heroes and then finds the desired hero + by filtering for the one with the matching `id`. + That's fine in a simulation. It's wasteful to ask a real server for _all_ heroes when we only want one. + Most web APIs support a _get-by-id_ request in the form `api/hero/:id` (e.g., `api/hero/11`). - Although we made significant *internal* changes to `getHeroes()`, the public signature did not change. - We still return a !{_Promise}. We won't have to update any of the components that call `getHeroes()`. + Update the `HeroService.getHero` method to make a _get-by-id_ request, + applying what we just learned to write `getHeroes`: ++makeExcerpt('app/hero.service.ts', 'getHero', '') +:marked + It's almost the same as `getHeroes`. + The URL identifies _which_ hero the server should update by encoding the hero id into the URL + to match the `api/hero/:id` pattern. + + We also adjust to the fact that the `data` in the response is a single hero object rather than !{_an} !{_array}. + + ### Unchanged _getHeroes_ API + + Although we made significant *internal* changes to `getHeroes()` and `getHero()`, + the public signatures did not change. + We still return a !{_Promise} from both methods. + We won't have to update any of the components that call them. - Our stakeholders are thrilled with the added flexibility from the API integration. + Our stakeholders are thrilled with the web API integration so far. Now they want the ability to create and delete heroes. Let's see first what happens when we try to update a hero's details. @@ -230,15 +250,12 @@ block get-heroes-details it. As we type, the hero name is updated in the view heading. But when we hit the `Back` button, the changes are lost! -.l-sub-section - :marked - Updates weren't lost before, what's happening? - When the app used a list of mock heroes, changes were made directly to the - hero objects in the single, app-wide shared list. Now that we are fetching data - from a server, if we want changes to persist, we'll need to write them back to - the server. + Updates weren't lost before. What changed? + When the app used a list of mock heroes, updates were applied directly to the + hero objects within the single, app-wide, shared list. Now that we are fetching data + from a server, if we want changes to persist, we'll need to write them back to + the server. -:marked ### Save hero details Let's ensure that edits to a hero's name aren't lost. Start by adding, diff --git a/public/docs/ts/latest/tutorial/toh-pt6.jade b/public/docs/ts/latest/tutorial/toh-pt6.jade index 74fb1b2f9e..46baa9c0cc 100644 --- a/public/docs/ts/latest/tutorial/toh-pt6.jade +++ b/public/docs/ts/latest/tutorial/toh-pt6.jade @@ -228,7 +228,7 @@ block get-heroes-details The URL identifies _which_ hero the server should update by encoding the hero id into the URL to match the `api/hero/:id` pattern. - We also adjust to the fact that the `data` in the response is a single hero object rather than array. + We also adjust to the fact that the `data` in the response is a single hero object rather than !{_an} !{_array}. ### Unchanged _getHeroes_ API