+ ''',
+ inputs: const ['hero'])
+class HeroDetailComponent {
+ Hero hero;
+}
diff --git a/public/docs/_examples/toh-4/dart/lib/hero_service.dart b/public/docs/_examples/toh-4/dart/lib/hero_service.dart
new file mode 100644
index 0000000000..4fa0b97e1c
--- /dev/null
+++ b/public/docs/_examples/toh-4/dart/lib/hero_service.dart
@@ -0,0 +1,23 @@
+// #docplaster
+// #docregion
+import 'dart:async';
+
+import 'package:angular2/core.dart';
+
+import 'hero.dart';
+import 'mock_heroes.dart';
+
+@Injectable()
+class HeroService {
+ //#docregion get-heroes
+ Future> getHeroes() async => mockHeroes;
+ //#enddocregion get-heroes
+
+ // See the "Take it slow" appendix
+ //#docregion get-heroes-slowly
+ Future> getHeroesSlowly() {
+ return new Future.delayed(const Duration(seconds: 2), () => mockHeroes);
+ }
+ //#enddocregion get-heroes-slowly
+}
+// #enddocregion
diff --git a/public/docs/_examples/toh-4/dart/lib/hero_service_1.dart b/public/docs/_examples/toh-4/dart/lib/hero_service_1.dart
new file mode 100644
index 0000000000..c95aeea7f8
--- /dev/null
+++ b/public/docs/_examples/toh-4/dart/lib/hero_service_1.dart
@@ -0,0 +1,28 @@
+// #docplaster
+// #docregion final
+// #docregion empty-class
+import 'package:angular2/core.dart';
+
+// #enddocregion empty-class
+import 'hero.dart';
+import 'mock_heroes.dart';
+
+// #docregion getHeroes-stub
+@Injectable()
+class HeroService {
+// #enddocregion getHeroes-stub
+// #enddocregion empty-class
+// #enddocregion final
+ /*
+// #docregion getHeroes-stub
+ List getHeroes() {}
+// #enddocregion getHeroes-stub
+ */
+// #docregion final
+ List getHeroes() => mockHeroes;
+// #docregion empty-class
+// #docregion getHeroes-stub
+}
+// #enddocregion getHeroes-stub
+// #enddocregion empty-class
+// #enddocregion final
diff --git a/public/docs/_examples/toh-4/dart/lib/mock_heroes.dart b/public/docs/_examples/toh-4/dart/lib/mock_heroes.dart
new file mode 100644
index 0000000000..55434761a2
--- /dev/null
+++ b/public/docs/_examples/toh-4/dart/lib/mock_heroes.dart
@@ -0,0 +1,16 @@
+// #docregion
+import 'hero.dart';
+
+final List mockHeroes = [
+ new Hero(11, "Mr. Nice"),
+ new Hero(12, "Narco"),
+ new Hero(13, "Bombasto"),
+ new Hero(14, "Celeritas"),
+ new Hero(15, "Magneta"),
+ new Hero(16, "RubberMan"),
+ new Hero(17, "Dynama"),
+ new Hero(18, "Dr IQ"),
+ new Hero(19, "Magma"),
+ new Hero(20, "Tornado")
+];
+// #enddocregion
\ No newline at end of file
diff --git a/public/docs/_examples/toh-4/dart/pubspec.yaml b/public/docs/_examples/toh-4/dart/pubspec.yaml
new file mode 100644
index 0000000000..f4d1c8caa0
--- /dev/null
+++ b/public/docs/_examples/toh-4/dart/pubspec.yaml
@@ -0,0 +1,15 @@
+name: angular2_tour_of_heroes
+version: 0.0.1
+environment:
+ sdk: '>=1.13.0 <2.0.0'
+dependencies:
+ angular2: 2.0.0-beta.15
+ browser: ^0.10.0
+ dart_to_js_script_rewriter: ^1.0.1
+transformers:
+- angular2:
+ platform_directives:
+ - package:angular2/common.dart#COMMON_DIRECTIVES
+ platform_pipes:
+ - package:angular2/common.dart#COMMON_PIPES
+ entry_points: web/main.dart
diff --git a/public/docs/_examples/toh-4/dart/web/index.html b/public/docs/_examples/toh-4/dart/web/index.html
new file mode 100644
index 0000000000..059daeed4c
--- /dev/null
+++ b/public/docs/_examples/toh-4/dart/web/index.html
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+ Loading...
+
+
diff --git a/public/docs/_examples/toh-4/dart/web/main.dart b/public/docs/_examples/toh-4/dart/web/main.dart
new file mode 100644
index 0000000000..81c22cd91d
--- /dev/null
+++ b/public/docs/_examples/toh-4/dart/web/main.dart
@@ -0,0 +1,9 @@
+// #docregion pt1
+import 'package:angular2/platform/browser.dart';
+
+import 'package:angular2_tour_of_heroes/app_component.dart';
+
+main() {
+ bootstrap(AppComponent);
+}
+// #enddocregion pt1
diff --git a/public/docs/_examples/toh-4/dart/web/main_1.dart b/public/docs/_examples/toh-4/dart/web/main_1.dart
new file mode 100644
index 0000000000..7d3d59c77d
--- /dev/null
+++ b/public/docs/_examples/toh-4/dart/web/main_1.dart
@@ -0,0 +1,9 @@
+// #docregion pt1
+import 'package:angular2/platform/browser.dart';
+
+import 'package:angular2_tour_of_heroes/app_component_1.dart';
+
+main() {
+ bootstrap(AppComponent);
+}
+// #enddocregion pt1
diff --git a/public/docs/_examples/toh-5/dart/pubspec.yaml b/public/docs/_examples/toh-5/dart/pubspec.yaml
index 2f88d9250e..699cb6bdae 100644
--- a/public/docs/_examples/toh-5/dart/pubspec.yaml
+++ b/public/docs/_examples/toh-5/dart/pubspec.yaml
@@ -5,12 +5,14 @@ version: 0.0.1
environment:
sdk: '>=1.13.0 <2.0.0'
dependencies:
- angular2: 2.0.0-beta.14
+ angular2: 2.0.0-beta.15
browser: ^0.10.0
dart_to_js_script_rewriter: ^1.0.1
transformers:
- angular2:
- platform_directives: package:angular2/common.dart#COMMON_DIRECTIVES
- platform_pipes: package:angular2/common.dart#COMMON_PIPES
+ platform_directives:
+ - package:angular2/common.dart#COMMON_DIRECTIVES
+ platform_pipes:
+ - package:angular2/common.dart#COMMON_PIPES
entry_points: web/main.dart
- dart_to_js_script_rewriter
diff --git a/public/docs/_examples/toh-5/dart/web/index.html b/public/docs/_examples/toh-5/dart/web/index.html
index db501e102e..0d2d000077 100644
--- a/public/docs/_examples/toh-5/dart/web/index.html
+++ b/public/docs/_examples/toh-5/dart/web/index.html
@@ -3,8 +3,8 @@
-
-
+
+
Angular 2 Tour of Heroes
diff --git a/public/docs/_examples/user-input/dart/pubspec.yaml b/public/docs/_examples/user-input/dart/pubspec.yaml
index 5704281d09..c069b15ffa 100644
--- a/public/docs/_examples/user-input/dart/pubspec.yaml
+++ b/public/docs/_examples/user-input/dart/pubspec.yaml
@@ -5,7 +5,7 @@ version: 0.0.1
environment:
sdk: '>=1.13.0 <2.0.0'
dependencies:
- angular2: 2.0.0-beta.14
+ angular2: 2.0.0-beta.15
browser: ^0.10.0
dart_to_js_script_rewriter: ^1.0.1
transformers:
diff --git a/public/docs/dart/latest/quickstart.jade b/public/docs/dart/latest/quickstart.jade
index abbf191bc5..3d17db49c6 100644
--- a/public/docs/dart/latest/quickstart.jade
+++ b/public/docs/dart/latest/quickstart.jade
@@ -41,7 +41,7 @@ p.
specify the angular2 and browser packages as dependencies,
as well as the angular2 transformer.
Angular 2 is still changing, so provide an exact version:
- 2.0.0-beta.14.
+ 2.0.0-beta.15.
+makeExample('quickstart/dart/pubspec.yaml', 'no-rewriter', 'pubspec.yaml')
diff --git a/public/docs/dart/latest/tutorial/toh-pt4.jade b/public/docs/dart/latest/tutorial/toh-pt4.jade
index 7c488613dd..238f23e06f 100644
--- a/public/docs/dart/latest/tutorial/toh-pt4.jade
+++ b/public/docs/dart/latest/tutorial/toh-pt4.jade
@@ -1,14 +1,399 @@
include ../_util-fns
:marked
- We're working on the Dart version of this case study.
- In the meantime, please see these resources:
+ # Services
+ The Tour of Heroes is evolving and we anticipate adding more components in the near future.
- * [Services](/docs/ts/latest/tutorial/toh-pt4.html):
- The TypeScript version of this chapter
+ Multiple components will need access to hero data and we don't want to copy and
+ paste the same code over and over.
+ Instead, we'll create a single reusable data service and learn to
+ inject it in the components that need it.
- * [Dart source code](https://github.com/angular/angular.io/tree/master/public/docs/_examples/toh-5/dart):
- A preliminary Dart version of the Tour of Heroes app,
- featuring the hero editor, a master/detail page,
- multiple components, services, and routing
+ Refactoring data access to a separate service keeps the component lean and focused on supporting the view.
+ It also makes it easier to unit test the component with a mock service.
+ Because data services are invariably asynchronous,
+ we'll finish the chapter with a promise-based version of the data service.
+
+ The complete source code for the example app in this chapter is
+ [in GitHub](https://github.com/angular/angular.io/tree/master/public/docs/_examples/toh-4/dart).
+
+.l-main-section
+:marked
+ ## Where We Left Off
+ Before we continue with our Tour of Heroes, let’s verify we have the following structure.
+ If not, we’ll need to go back and follow the previous chapters.
+
+.filetree
+ .file angular2_tour_of_heroes
+ .children
+ .file lib
+ .children
+ .file app_component.dart
+ .file hero.dart
+ .file hero_detail_component.dart
+ .file web
+ .children
+ .file index.html
+ .file main.dart
+ .file pubspec.yaml
+: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(format="." language="bash").
+ pub serve
+
+:marked
+ The application runs and updates automatically as we continue to build the Tour of Heroes.
+
+ ## Creating a Hero Service
+ Our stakeholders have shared their larger vision for our app.
+ They tell us they want to show the heroes in various ways on different pages.
+ We already can select a hero from a list.
+ Soon we'll add a dashboard with the top performing heroes and create a separate view for editing hero details.
+ All three views need hero data.
+
+ At the moment the `AppComponent` defines mock heroes for display.
+ We have at least two objections.
+ First, defining heroes is not the component's job.
+ Second, we can't easily share that list of heroes with other components and views.
+
+ We can refactor this hero data acquisition business to a single service that provides heroes and
+ share that service with all components that need heroes.
+
+ ### Create the HeroService
+ Create a file in the `lib` folder called `hero_service.dart`.
+.l-sub-section
+ :marked
+ We've adopted a convention in which we spell the name of a service in lowercase followed by `_service`.
+ If the service name were multi-word, we'd spell the base filename with lower underscore case (AKA "snake_case").
+ The `SpecialSuperHeroService` would be defined in the `special_super_hero_service.dart` file.
+:marked
+ We name the class `HeroService`.
+
++makeExample('toh-4/dart/lib/hero_service_1.dart', 'empty-class', 'hero_service.dart (class)')(format=".")
+
+:marked
+ ### Injectable Services
+ Notice that we used an `@Injectable()` annotation.
+.callout.is-helpful
+ :marked
+ **Don't forget the parentheses!** Neglecting them leads to an error that's difficult to diagnose.
+:marked
+ Dart sees the `@Injectable()` annotation and emits metadata about our service,
+ metadata that Angular may need to inject other dependencies into this service.
+
+ The `HeroService` doesn't have any dependencies *at the moment*. Add the annotation anyway.
+ It is a "best practice" to apply the `@Injectable()` annotation *from the start*
+ both for consistency and for future-proofing.
+
+:marked
+ ### Getting Heroes
+ Add a `getHeroes` method stub.
++makeExample('toh-4/dart/lib/hero_service_1.dart', 'getHeroes-stub', 'hero_service.dart (getHeroes stub)')(format=".")
+:marked
+ We're holding back on the implementation for a moment to make an important point.
+
+ The consumer of our service doesn't know how the service gets the data.
+ Our `HeroService` could get `Hero` data from anywhere.
+ It could get the data from a web service or local storage
+ or from a mock data source.
+
+ That's the beauty of removing data access from the component.
+ We can change our minds about the implementation as often as we like,
+ for whatever reason, without touching any of the components that need heroes.
+
+
+ ### Mock Heroes
+ We already have mock `Hero` data sitting in the `AppComponent`. It doesn't belong there. It doesn't belong *here* either.
+ We'll move the mock data to its own file.
+
+ Cut the the `mockHeroes` list from `app_component.dart` and paste it to a new file in the `lib` folder named `mock_heroes.dart`.
+ We copy the `import 'hero.dart'` statement as well because the heroes list uses the `Hero` class.
+
++makeExample('toh-4/dart/lib/mock_heroes.dart', null, 'mock_heroes.dart (Heroes list)')
+:marked
+ Meanwhile, back in `app_component.dart` where we cut away the `mockHeroes` list,
+ we leave behind an uninitialized `heroes` property:
++makeExample('toh-4/dart/lib/app_component_1.dart', 'heroes-prop', 'app_component.dart (heroes property)')(format=".")
+:marked
+ ### Return Mocked Heroes
+ Back in the `HeroService` we import the mock `mockHeroes` and return it from the `getHeroes` method.
+ Our `HeroService` looks like this:
++makeExample('toh-4/dart/lib/hero_service_1.dart', 'final', 'hero_service.dart')(format=".")
+:marked
+ ### Use the Hero Service
+ We're ready to use the `HeroService` in other components starting with our `AppComponent`.
+
+ We begin, as usual, by importing the thing we want to use, the `HeroService`.
++makeExample('toh-4/dart/lib/app_component.dart', 'hero-service-import', 'app_component.dart (import HeroService)')(format=".")
+:marked
+ Importing the service allows us to *reference* it in our code.
+ How should the `AppComponent` acquire a runtime concrete `HeroService` instance?
+
+ ### Do we *new* the *HeroService*? No way!
+ We could create a new instance of the `HeroService` with "new" like this:
++makeExample('toh-4/dart/lib/app_component_1.dart', 'new-service')(format=".")
+:marked
+ That's a bad idea for several reasons including
+
+ * Our component has to know how to create a `HeroService`.
+ If we ever change the `HeroService` constructor,
+ we'll have to find every place we create the service and fix it.
+ Running around patching code is error prone and adds to the test burden.
+
+ * We create a new service each time we use "new".
+ What if the service should cache heroes and share that cache with others?
+ We couldn't do that.
+
+ * We're locking the `AppComponent` into a specific implementation of the `HeroService`.
+ It will be hard to switch implementations for different scenarios.
+ Can we operate offline?
+ Will we need different mocked versions under test?
+ Not easy.
+
+ *What if ... what if ... Hey, we've got work to do!*
+
+ We get it. Really we do.
+ But it is so ridiculously easy to avoid these problems that there is no excuse for doing it wrong.
+
+ ### Inject the *HeroService*
+
+ Three lines replace the one line of *new*:
+ 1. We add a property.
+ 1. We add a constructor that sets the property.
+ 1. We add to the component's `providers` metadata.
+
+ Here are the property and the constructor:
++makeExample('toh-4/dart/lib/app_component_1.dart', 'ctor', 'app_component.dart (constructor)')(format='.')
+:marked
+ The constructor does nothing except set the `_heroService`
+ property. The `HeroService` type of `_heroService`
+ identifies the constructor's parameter as
+ a `HeroService` injection site.
+
+ Now Angular will know to supply an instance of the `HeroService` when it creates a new `AppComponent`.
+
+ Angular has to get that instance from somewhere. That's the role of the Angular *Dependency Injector*.
+ The **Injector** has a **container** of previously created services.
+ Either it finds and returns a pre-existing `HeroService` from its container or it creates a new instance, adds
+ it to the container, and returns it to Angular.
+
+.l-sub-section
+ :marked
+ Learn more about Dependency Injection in the [Dependency Injection](../guide/dependency-injection.html) chapter.
+:marked
+ The *injector* does not know yet how to create a `HeroService`.
+ If we ran our code now, Angular would fail with an error:
+code-example(format="." language="html").
+ EXCEPTION: No provider for HeroService! (AppComponent -> HeroService)
+:marked
+ We have to teach the *injector* how to make a `HeroService` by registering a `HeroService` **provider**.
+ Do that by adding the following `providers` parameter to the bottom of the component metadata
+ in the `@Component` annotation.
+
++makeExample('toh-4/dart/lib/app_component_1.dart', 'providers', 'app_component.dart (providing HeroService)')(format=".")
+:marked
+ The `providers` parameter tells Angular to create a fresh instance of the `HeroService` when it creates a new `AppComponent`.
+ The `AppComponent` can use that service to get heroes and so can every child component of its component tree.
+
+.l-sub-section
+ :marked
+ ### Services and the component tree
+
+ Recall that the `AppComponent` creates an instance of `HeroDetail` by virtue of the
+ `` tag at the bottom of its template. That `HeroDetail` is a child of the `AppComponent`.
+
+ If the `HeroDetailComponent` needed its parent component's `HeroService`,
+ it would ask Angular to inject the service into its constructor which would look just like the one for `AppComponent`:
+ +makeExample('toh-4/dart/lib/app_component_1.dart', 'ctor', 'hero_detail_component.dart (constructor)')(format=".")
+ :marked
+ The `HeroDetailComponent` must *not* repeat its parent's `providers` list! Guess [why](#shadow-provider).
+
+ The `AppComponent` is the top level component of our application.
+ There should be only one instance of that component and only one instance of the `HeroService` in our entire app.
+:marked
+ ### *getHeroes* in the *AppComponent*
+ We've got the service in a `_heroService` private variable. Let's use it.
+
+ We pause to think. We can call the service and get the data in one line.
++makeExample('toh-4/dart/lib/app_component_1.dart', 'get-heroes')(format=".")
+:marked
+ We don't really need a dedicated method to wrap one line. We write it anyway:
++makeExample('toh-4/dart/lib/app_component_1.dart', 'getHeroes', 'app_component.dart (getHeroes)')(format=".")
+
+
+:marked
+ ### The *ngOnInit* Lifecycle Hook
+ `AppComponent` should fetch and display heroes without a fuss.
+ Where do we call the `getHeroes` method? In a constructor? We do *not*!
+
+ Years of experience and bitter tears have taught us to keep complex logic out of the constructor,
+ especially anything that might call a server as a data access method is sure to do.
+
+ The constructor is for simple initializations like wiring constructor parameters to properties.
+ It's not for heavy lifting. We should be able to create a component in a test and not worry that it
+ might do real work — like calling a server! — before we tell it to do so.
+
+ If not the constructor, something has to call `getHeroes`.
+
+ Angular will call it if we implement the Angular **ngOnInit** *Lifecycle Hook*.
+ Angular offers a number of interfaces for tapping into critical moments in the component lifecycle:
+ at creation, after each change, and at its eventual destruction.
+
+ Each interface has a single method. When the component implements that method, Angular calls it at the appropriate time.
+.l-sub-section
+ :marked
+ Learn more about lifecycle hooks in the [Lifecycle Hooks](../guide/lifecycle-hooks.html) chapter.
+:marked
+ Here's the essential outline for the `OnInit` interface:
++makeExample('toh-4/dart/lib/app_component_1.dart', 'on-init', 'app_component.dart (OnInit protocol)')(format=".")
+:marked
+ We write an `ngOnInit` method with our initialization logic inside and leave it to Angular to call it
+ at the right time. In our case, we initialize by calling `getHeroes`.
++makeExample('toh-4/dart/lib/app_component_1.dart', 'ng-on-init', 'app_component.dart (OnInit protocol)')(format=".")
+:marked
+ Our application should be running as expected, showing a list of heroes and a hero detail view
+ when we click on a hero name.
+
+ We're getting closer. But something isn't quite right.
+
+ ## Async Services and Futures
+ Our `HeroService` returns a list of mock heroes immediately.
+ Its `getHeroes` signature is synchronous
++makeExample('toh-4/dart/lib/app_component_1.dart', 'get-heroes')(format=".")
+:marked
+ Ask for heroes and they are there in the returned result.
+
+ Someday we're going to get heroes from a remote server. We don’t call http yet, but we aspire to in later chapters.
+
+ When we do, we'll have to wait for the server to respond and we won't be able to block the UI while we wait,
+ even if we want to (which we shouldn't) because the browser won't block.
+
+ We'll have to use some kind of asynchronous technique and that will change the signature of our `getHeroes` method.
+
+ We'll use *futures*.
+
+ ### The Hero Service returns a future
+
+ We ask an asynchronous service to do some work and give us the result in the future.
+ The service does that work (somewhere) and eventually it updates the future with the results of the work or an error.
+.l-sub-section
+ :marked
+ We are simplifying. Learn about Futures in the tutorial
+ [Asynchronous Programming: Futures](https://www.dartlang.org/docs/tutorials/futures/).
+:marked
+ Update the `HeroService` with this future-returning `getHeroes` method:
++makeExample('toh-4/dart/lib/hero_service.dart', 'get-heroes', 'hero_service.dart (getHeroes)')(format=".")
+:marked
+ We're still mocking the data. We're simulating the behavior of an ultra-fast, zero-latency server,
+ by returning a future that will quickly resolve with our mock heroes as the result.
+
+.l-sub-section
+ :marked
+ Marking the method's body with `async` makes the method immediately return a `Future` object.
+ That future later completes with the method's return value.
+ For more information on async functions, see
+ [Declaring async functions](https://www.dartlang.org/docs/dart-up-and-running/ch02.html#async) in the Dart language tour.
+
+:marked
+ ### Act on the Futures
+ Returning to the `AppComponent` and its `getHeroes` method, we see that it still looks like this:
++makeExample('toh-4/dart/lib/app_component_1.dart', 'getHeroes', 'app_component.dart (getHeroes - old)')(format=".")
+:marked
+ As a result of our change to `HeroService`, we're now setting `heroes` to a future rather than a list of heroes.
+
+ We have to change our implementation to *act on the future when it resolves*.
+ We can *await* the future to resolve, and then display the heroes:
++makeExample('toh-4/dart/lib/app_component.dart', 'get-heroes', 'app_component.dart (getHeroes - revised)')(format=".")
+:marked
+ Our code waits until the future completes, and then
+ sets the component's `heroes` property to the list of heroes returned by the service. That's all there is to it!
+
+ Our app should still be running, still showing a list of heroes, and still
+ responding to a name selection with a detail view.
+.l-sub-section
+ :marked
+ Check out the "[Take it slow](#slow)" appendix to see what the app might be like with a poor connection.
+:marked
+ ### Review the App Structure
+ Let’s verify that we have the following structure after all of our good refactoring in this chapter:
+
+.filetree
+ .file angular2_tour_of_heroes
+ .children
+ .file lib
+ .children
+ .file app_component.dart
+ .file hero.dart
+ .file hero_detail_component.dart
+ .file hero_service.dart
+ .file mock_heroes.dart
+ .file web
+ .children
+ .file index.html
+ .file main.dart
+ .file pubspec.yaml
+:marked
+ Here are the code files we discussed in this chapter.
+
++makeTabs(`
+ toh-4/dart/lib/hero_service.dart,
+ toh-4/dart/lib/app_component.dart,
+ toh-4/dart/lib/mock_heroes.dart
+ `,'',`
+ lib/hero_service.dart,
+ lib/app_component.dart,
+ lib/mock_heroes.dart
+ `)
+:marked
+ ## The Road We’ve Travelled
+ Let’s take stock of what we’ve built.
+
+ * We created a service class that can be shared by many components
+ * We used the `ngOnInit` Lifecycle Hook to get our heroes when our `AppComponent` activates
+ * We defined our `HeroService` as a provider for our `AppComponent`
+ * We created mock hero data and imported them into our service
+ * We designed our service to return a future and our component to get our data from the future
+
+
+ ### The Road Ahead
+ Our Tour of Heroes has become more reusable using shared components and services.
+ We want to create a dashboard, add menu links that route between the views, and format data in a template.
+ As our app evolves, we’ll learn how to design it to make it easier to grow and maintain.
+
+ We learn about Angular Component Router and navigation among the views in the [next tutorial](toh-pt5.html) chapter.
+
+.l-main-section
+
+:marked
+ ### Appendix: Take it slow
+
+ We can simulate a slow connection.
+
+ Add the following `getHeroesSlowly` method to the `HeroService`:
++makeExample('toh-4/dart/lib/hero_service.dart', 'get-heroes-slowly', 'hero_service.dart (getHeroesSlowly)')(format=".")
+:marked
+ Like `getHeroes`, it also returns a future.
+ But this future waits 2 seconds before resolving the future with mock heroes.
+
+ Back in the `AppComponent`, replace
+ `_heroService.getHeroes` with `_heroService.getHeroesSlowly`
+ and see how the app behaves.
+
+.l-main-section
+
+:marked
+ ### Appendix: Shadowing the parent's service
+
+ We stated [earlier](#child-component) that if we injected the parent `AppComponent` `HeroService`
+ into the `HeroDetailComponent`, *we must not add a providers list* to the `HeroDetailComponent` metadata.
+
+ Why? Because that tells Angular to create a new instance of the `HeroService` at the `HeroDetailComponent` level.
+ The `HeroDetailComponent` doesn't want its *own* service instance; it wants its *parent's* service instance.
+ Adding the `providers` list creates a new service instance that shadows the parent instance.
+
+ Think carefully about where and when to register a provider.
+ Understand the scope of that registration. Be careful not to create a new service instance at the wrong level.