Merge remote-tracking branch 'origin/master'

# Conflicts:
#	public/docs/ts/latest/tutorial/toh-pt5.jade
This commit is contained in:
Zhicheng Wang 2016-06-15 23:10:41 +08:00
commit 6a5f4a0fc2
20 changed files with 542 additions and 516 deletions

View File

@ -13,6 +13,7 @@ import 'hero_service.dart';
@Component( @Component(
selector: 'my-app', selector: 'my-app',
// #docregion template
template: ''' template: '''
<h1>{{title}}</h1> <h1>{{title}}</h1>
<h2>My Heroes</h2> <h2>My Heroes</h2>
@ -25,6 +26,7 @@ import 'hero_service.dart';
</ul> </ul>
<my-hero-detail [hero]="selectedHero"></my-hero-detail> <my-hero-detail [hero]="selectedHero"></my-hero-detail>
''', ''',
// #enddocregion template
styles: const [ styles: const [
''' '''
.selected { .selected {

View File

@ -1,5 +1,4 @@
/* #docplaster */ /* #docregion */
/* #docregion css */
h1 { h1 {
font-size: 1.2em; font-size: 1.2em;
color: #999; color: #999;
@ -28,4 +27,3 @@ nav a:hover {
nav a.router-link-active { nav a.router-link-active {
color: #039be5; color: #039be5;
} }
/* #enddocregion css */

View File

@ -27,20 +27,19 @@ import 'package:angular2_tour_of_heroes/hero_detail_component.dart';
directives: const [ROUTER_DIRECTIVES], directives: const [ROUTER_DIRECTIVES],
providers: const [HeroService, ROUTER_PROVIDERS]) providers: const [HeroService, ROUTER_PROVIDERS])
@RouteConfig(const [ @RouteConfig(const [
// #docregion dashboard-route // #docregion dashboard-route
const Route( const Route(
path: '/dashboard', path: '/dashboard',
name: 'Dashboard', name: 'Dashboard',
component: DashboardComponent, component: DashboardComponent,
useAsDefault: true), useAsDefault: true),
// #enddocregion dashboard-route // #enddocregion dashboard-route
// #docregion hero-detail-route // #docregion hero-detail-route
const Route( const Route(
path: '/detail/:id', name: 'HeroDetail', component: HeroDetailComponent), path: '/detail/:id', name: 'HeroDetail', component: HeroDetailComponent),
// #enddocregion hero-detail-route // #enddocregion hero-detail-route
const Route(path: '/heroes', name: 'Heroes', component: HeroesComponent) const Route(path: '/heroes', name: 'Heroes', component: HeroesComponent)
]) ])
class AppComponent { class AppComponent {
String title = 'Tour of Heroes'; String title = 'Tour of Heroes';
} }
// #enddocregion

View File

@ -15,12 +15,11 @@ import 'heroes_component.dart';
<my-heroes></my-heroes>''', <my-heroes></my-heroes>''',
directives: const [HeroesComponent], directives: const [HeroesComponent],
providers: const [ providers: const [
// #enddocregion // #enddocregion
ROUTER_PROVIDERS, ROUTER_PROVIDERS,
// #docregion // #docregion
HeroService HeroService
]) ])
class AppComponent { class AppComponent {
String title = 'Tour of Heroes'; String title = 'Tour of Heroes';
} }
// #enddocregion

View File

@ -10,12 +10,12 @@ import 'heroes_component.dart';
@Component( @Component(
selector: 'my-app', selector: 'my-app',
// #docregion template // #docregion template
template: ''' template: '''
<h1>{{title}}</h1> <h1>{{title}}</h1>
<a [routerLink]="['Heroes']">Heroes</a> <a [routerLink]="['Heroes']">Heroes</a>
<router-outlet></router-outlet>''', <router-outlet></router-outlet>''',
// #enddocregion template // #enddocregion template
// #docregion directives-and-providers // #docregion directives-and-providers
directives: const [ROUTER_DIRECTIVES], directives: const [ROUTER_DIRECTIVES],
providers: const [ROUTER_PROVIDERS, HeroService] providers: const [ROUTER_PROVIDERS, HeroService]
@ -29,4 +29,3 @@ import 'heroes_component.dart';
class AppComponent { class AppComponent {
String title = 'Tour of Heroes'; String title = 'Tour of Heroes';
} }
// #enddocregion

View File

@ -1,4 +1,3 @@
/* #docplaster */
/* #docregion */ /* #docregion */
[class*='col-'] { [class*='col-'] {
float: left; float: left;
@ -60,4 +59,3 @@ h4 {
min-width: 60px; min-width: 60px;
} }
} }
/* #enddocregion */

View File

@ -1,5 +1,7 @@
// #docplaster // #docplaster
// #docregion // #docregion
import 'dart:async';
import 'package:angular2/core.dart'; import 'package:angular2/core.dart';
// #docregion import-router // #docregion import-router
import 'package:angular2/router.dart'; import 'package:angular2/router.dart';
@ -16,22 +18,25 @@ import 'hero_service.dart';
// #docregion css // #docregion css
styleUrls: const ['dashboard_component.css'] styleUrls: const ['dashboard_component.css']
// #enddocregion css // #enddocregion css
) )
// #docregion component // #docregion component
class DashboardComponent implements OnInit { class DashboardComponent implements OnInit {
List<Hero> heroes; List<Hero> heroes;
// #docregion ctor
// #docregion ctor
final Router _router; final Router _router;
final HeroService _heroService; final HeroService _heroService;
DashboardComponent(this._heroService, this._router); DashboardComponent(this._heroService, this._router);
// #enddocregion ctor
ngOnInit() async => // #enddocregion ctor
Future<Null> ngOnInit() async {
heroes = (await _heroService.getHeroes()).getRange(1, 5).toList(); heroes = (await _heroService.getHeroes()).getRange(1, 5).toList();
}
// #docregion goto-detail // #docregion goto-detail
gotoDetail(Hero hero) { void gotoDetail(Hero hero) {
var link = [ var link = [
'HeroDetail', 'HeroDetail',
{'id': hero.id.toString()} {'id': hero.id.toString()}
@ -40,4 +45,3 @@ class DashboardComponent implements OnInit {
} }
// #enddocregion goto-detail // #enddocregion goto-detail
} }
// #enddocregion

View File

@ -1,9 +1,9 @@
<!-- #docregion --> <!-- #docregion -->
<h3>Top Heroes</h3> <h3>Top Heroes</h3>
<div class="grid grid-pad"> <div class="grid grid-pad">
<!-- #docregion click --> <!-- #docregion click -->
<div *ngFor="let hero of heroes" (click)="gotoDetail(hero)" class="col-1-4" > <div *ngFor="let hero of heroes" (click)="gotoDetail(hero)" class="col-1-4" >
<!-- #enddocregion click --> <!-- #enddocregion click -->
<div class="module hero"> <div class="module hero">
<h4>{{hero.name}}</h4> <h4>{{hero.name}}</h4>
</div> </div>

View File

@ -1,5 +1,7 @@
// #docplaster // #docplaster
// #docregion imports // #docregion imports
import 'dart:async';
import 'package:angular2/core.dart'; import 'package:angular2/core.dart';
import 'hero.dart'; import 'hero.dart';
@ -9,17 +11,16 @@ import 'hero_service.dart';
// #docregion component // #docregion component
@Component( @Component(
selector: 'my-dashboard', selector: 'my-dashboard',
templateUrl: 'dashboard_component.html' templateUrl: 'dashboard_component.html')
)
class DashboardComponent implements OnInit { class DashboardComponent implements OnInit {
List<Hero> heroes; List<Hero> heroes;
final HeroService _heroService; final HeroService _heroService;
DashboardComponent(this._heroService); DashboardComponent(this._heroService);
ngOnInit() async => Future<Null> ngOnInit() async {
heroes = (await _heroService.getHeroes()).getRange(1, 5).toList(); heroes = (await _heroService.getHeroes()).getRange(1, 5).toList();
}
gotoDetail(){ /* not implemented yet */} gotoDetail() {/* not implemented yet */}
} }
// #enddocregion component

View File

@ -1,6 +1,7 @@
// #docplaster // #docplaster
// #docregion // #docregion
// #docregion v2 // #docregion v2
import 'dart:async';
import 'dart:html'; import 'dart:html';
// #docregion import-oninit // #docregion import-oninit
@ -20,37 +21,35 @@ import 'hero_service.dart';
selector: 'my-hero-detail', selector: 'my-hero-detail',
// #docregion template-url // #docregion template-url
templateUrl: 'hero_detail_component.html', templateUrl: 'hero_detail_component.html',
// #enddocregion template-url // #enddocregion template-url, v2
// #enddocregion v2
styleUrls: const ['hero_detail_component.css'] styleUrls: const ['hero_detail_component.css']
// #docregion v2 // #docregion v2
) )
// #enddocregion extract-template // #enddocregion extract-template
// #docregion implement // #docregion implement
class HeroDetailComponent implements OnInit { class HeroDetailComponent implements OnInit {
// #enddocregion implement // #enddocregion implement
Hero hero; Hero hero;
// #docregion ctor // #docregion ctor
final HeroService _heroService; final HeroService _heroService;
final RouteParams _routeParams; final RouteParams _routeParams;
HeroDetailComponent(this._heroService, this._routeParams); HeroDetailComponent(this._heroService, this._routeParams);
// #enddocregion ctor // #enddocregion ctor
// #docregion ng-oninit // #docregion ng-oninit
ngOnInit() async { Future<Null> ngOnInit() async {
// #docregion get-id // #docregion get-id
var id = int.parse(_routeParams.get('id')); var idString = _routeParams.get('id');
var id = int.parse(idString, onError: (_) => null);
// #enddocregion get-id // #enddocregion get-id
hero = await (_heroService.getHero(id)); if (id != null) hero = await (_heroService.getHero(id));
} }
// #enddocregion ng-oninit // #enddocregion ng-oninit
// #docregion go-back // #docregion go-back
goBack() { void goBack() {
window.history.back(); window.history.back();
} }
// #enddocregion go-back // #enddocregion go-back
} }
// #enddocregion v2
// #enddocregion

View File

@ -1,5 +1,3 @@
// #docplaster
// #docregion // #docregion
import 'dart:async'; import 'dart:async';
@ -10,18 +8,16 @@ import 'mock_heroes.dart';
@Injectable() @Injectable()
class HeroService { class HeroService {
Future<List<Hero>> getHeroes() async => HEROES; Future<List<Hero>> getHeroes() async => mockHeroes;
// See the "Take it slow" appendix // See the "Take it slow" appendix
Future<List<Hero>> getHeroesSlowly() { Future<List<Hero>> getHeroesSlowly() {
return new Future<List<Hero>>.delayed( return new Future<List<Hero>>.delayed(
const Duration(seconds: 2), () => HEROES // 2 seconds const Duration(seconds: 2), () => mockHeroes);
);
} }
//#docregion get-hero // #docregion get-hero
Future<Hero> getHero(int id) async => Future<Hero> getHero(int id) async =>
HEROES.where((hero) => hero.id == id).first; (await getHeroes()).firstWhere((hero) => hero.id == id);
//#enddocregion get-hero // #enddocregion get-hero
} }
// #enddocregion

View File

@ -9,22 +9,19 @@ import 'hero.dart';
import 'hero_detail_component.dart'; import 'hero_detail_component.dart';
import 'hero_service.dart'; import 'hero_service.dart';
// #docregion metadata // #docregion metadata, heroes-component-renaming
// #docregion heroes-component-renaming
@Component( @Component(
selector: 'my-heroes', selector: 'my-heroes',
// #enddocregion heroes-component-renaming // #enddocregion heroes-component-renaming
templateUrl: 'heroes_component.html', templateUrl: 'heroes_component.html',
styleUrls: const ['heroes_component.css'], styleUrls: const ['heroes_component.css'],
directives: const [HeroDetailComponent] directives: const [HeroDetailComponent]
// #docregion heroes-component-renaming // #docregion heroes-component-renaming
) )
// #enddocregion heroes-component-renaming // #enddocregion heroes-component-renaming, metadata
// #enddocregion metadata // #docregion class, heroes-component-renaming
// #docregion class
// #docregion heroes-component-renaming
class HeroesComponent implements OnInit { class HeroesComponent implements OnInit {
// #enddocregion heroes-component-renaming // #enddocregion heroes-component-renaming
final Router _router; final Router _router;
final HeroService _heroService; final HeroService _heroService;
List<Hero> heroes; List<Hero> heroes;
@ -32,7 +29,7 @@ class HeroesComponent implements OnInit {
HeroesComponent(this._heroService, this._router); HeroesComponent(this._heroService, this._router);
Future getHeroes() async { Future<Null> getHeroes() async {
heroes = await _heroService.getHeroes(); heroes = await _heroService.getHeroes();
} }
@ -42,10 +39,7 @@ class HeroesComponent implements OnInit {
void onSelect(Hero hero) { selectedHero = hero; } void onSelect(Hero hero) { selectedHero = hero; }
Future gotoDetail() => Future<Null> gotoDetail() =>
_router.navigate(['HeroDetail', {'id': selectedHero.id.toString()}]); _router.navigate(['HeroDetail', {'id': selectedHero.id.toString()}]);
// #docregion heroes-component-renaming // #docregion heroes-component-renaming
} }
// #enddocregion heroes-component-renaming
// #enddocregion class
// #enddocregion

View File

@ -17,5 +17,3 @@
</h2> </h2>
<button (click)="gotoDetail()">View Details</button> <button (click)="gotoDetail()">View Details</button>
</div> </div>
<!-- #enddocregion mini-detail -->
<!-- #enddocregion -->

View File

@ -1,6 +1,6 @@
import 'hero.dart'; import 'hero.dart';
final List<Hero> HEROES = [ final List<Hero> mockHeroes = [
new Hero(11, 'Mr. Nice'), new Hero(11, 'Mr. Nice'),
new Hero(12, 'Narco'), new Hero(12, 'Narco'),
new Hero(13, 'Bombasto'), new Hero(13, 'Bombasto'),

View File

@ -1,10 +1,11 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<!-- #docregion head --> <!-- #docregion head, base-href -->
<!-- #docregion base-href -->
<head> <head>
<base href="/"> <!-- For testing using pub serve directly --> <!-- For testing using pub serve directly use: -->
<!-- base href="/dart/web/" --> <!-- For testing in WebStorm --> <base href="/">
<!-- For testing in WebStorm use: -->
<!-- base href="/dart/web/" -->
<!-- #enddocregion base-href --> <!-- #enddocregion base-href -->
<title>Angular 2 Tour of Heroes</title> <title>Angular 2 Tour of Heroes</title>
<meta name="viewport" content="width=device-width, initial-scale=1"> <meta name="viewport" content="width=device-width, initial-scale=1">

View File

@ -2,6 +2,6 @@ import 'package:angular2/platform/browser.dart';
import 'package:angular2_tour_of_heroes/app_component.dart'; import 'package:angular2_tour_of_heroes/app_component.dart';
main() { void main() {
bootstrap(AppComponent); bootstrap(AppComponent);
} }

View File

@ -0,0 +1,24 @@
/* #docregion toh-excerpt */
/* Master Styles */
h1 {
color: #369;
font-family: Arial, Helvetica, sans-serif;
font-size: 250%;
}
h2, h3 {
color: #444;
font-family: Arial, Helvetica, sans-serif;
font-weight: lighter;
}
body {
margin: 2em;
}
body, input[text], button {
color: #888;
font-family: Cambria, Georgia;
}
/* . . . */
/* everywhere else */
* {
font-family: Arial, Helvetica, sans-serif;
}

View File

@ -3,10 +3,10 @@ include ../_util-fns
:marked :marked
# Routing Around the App # Routing Around the App
We received new requirements for our Tour of Heroes application: We received new requirements for our Tour of Heroes application:
* add a *Dashboard* view. * Add a *Dashboard* view.
* navigate between the *Heroes* and *Dashboard* views. * Navigate between the *Heroes* and *Dashboard* views.
* clicking on a hero in either view navigates to a detail view of the selected hero. * Clicking on a hero in either view navigates to a detail view of the selected hero.
* clicking a *deep link* in an email opens the detail view for a particular hero. * Clicking a *deep link* in an email opens the detail view for a particular hero.
When were done, users will be able to navigate the app like this: When were done, users will be able to navigate the app like this:
figure.image-display figure.image-display
@ -16,7 +16,7 @@ figure.image-display
.l-sub-section .l-sub-section
:marked :marked
The [Routing and Navigation](../guide/router.html) chapter covers the router in more detail The [Routing and Navigation](../guide/router.html) chapter covers the router in more detail
than we will in this tour. than we will in this tutorial.
p Run the #[+liveExampleLink2('', 'toh-5')] for this part. p Run the #[+liveExampleLink2('', 'toh-5')] for this part.
@ -54,13 +54,13 @@ code-example(language="bash").
The application runs and updates automatically as we continue to build the Tour of Heroes. The application runs and updates automatically as we continue to build the Tour of Heroes.
## Action plan ## Action plan
Here's our plan Here's our plan:
* turn `AppComponent` into an application shell that only handles navigation. * Turn `AppComponent` into an application shell that only handles navigation
* relocate the *Heroes* concerns within the current `AppComponent` to a separate `HeroesComponent` * Relocate the *Heroes* concerns within the current `AppComponent` to a separate `HeroesComponent`
* add routing * Add routing
* create a new `DashboardComponent` * Create a new `DashboardComponent`
* tie the *Dashboard* into the navigation structure. * Tie the *Dashboard* into the navigation structure
.l-sub-section .l-sub-section
:marked :marked
@ -82,13 +82,13 @@ code-example(language="bash").
Instead of moving anything out of `AppComponent`, we'll just rename it `HeroesComponent` Instead of moving anything out of `AppComponent`, we'll just rename it `HeroesComponent`
and create a new `AppComponent` shell separately. and create a new `AppComponent` shell separately.
The steps are: The steps are to rename:
* rename `app_component.dart` file to `heroes_component.dart`. * `app_component.dart` file to `heroes_component.dart`
* rename the `AppComponent` class to `HeroesComponent`. * `AppComponent` class to `HeroesComponent`
* rename the selector `my-app` to `my-heroes`. * Selector `my-app` to `my-heroes`
:marked :marked
+makeExample('toh-5/dart/lib/heroes_component.dart', 'heroes-component-renaming', 'lib/heroes_component.dart (renaming)')(format=".") +makeExample('toh-5/dart/lib/heroes_component.dart', 'heroes-component-renaming', 'lib/heroes_component.dart (showing renamings only)')(format=".")
:marked :marked
## Create *AppComponent* ## Create *AppComponent*
@ -149,14 +149,14 @@ code-example(language="bash").
The Angular router is a combination of multiple services (`ROUTER_PROVIDERS`), multiple directives (`ROUTER_DIRECTIVES`), The Angular router is a combination of multiple services (`ROUTER_PROVIDERS`), multiple directives (`ROUTER_DIRECTIVES`),
and a configuration annotation (`RouteConfig`). We'll get them all by importing `router.dart`: and a configuration annotation (`RouteConfig`). We'll get them all by importing `router.dart`:
+makeExample('toh-5/dart/lib/app_component_2.dart', 'import-router', 'app_component.dart (router imports)')(format=".") +makeExample('toh-5/dart/lib/app_component_2.dart', 'import-router', 'lib/app_component.dart (router imports)')(format=".")
:marked :marked
The *Component Router* is a service. Like any service, we have to make it The *Component Router* is a service. Like any service, we have to make it
available to the application by adding it to the `providers` list. available to the application by adding it to the `providers` list.
Let's update the `directives` and `providers` metadata lists to *include* the router assets. Let's update the `directives` and `providers` metadata lists to *include* the router assets.
+makeExample('toh-5/dart/lib/app_component_2.dart', 'directives-and-providers', 'app_component.dart (directives and providers)')(format=".") +makeExample('toh-5/dart/lib/app_component_2.dart', 'directives-and-providers', 'lib/app_component.dart (directives and providers)')(format=".")
:marked :marked
Notice that we also removed the `HeroesComponent` from the `directives` list. Notice that we also removed the `HeroesComponent` from the `directives` list.
`AppComponent` no longer shows heroes; that will be the router's job. `AppComponent` no longer shows heroes; that will be the router's job.
@ -171,7 +171,7 @@ code-example(language="bash").
pastes a URL into the browser address bar. pastes a URL into the browser address bar.
Let's define our first route, a route to the `HeroesComponent`. Let's define our first route, a route to the `HeroesComponent`.
+makeExample('toh-5/dart/lib/app_component_2.dart', 'route-config', 'app_component.dart (RouteConfig for heroes)')(format=".") +makeExample('toh-5/dart/lib/app_component_2.dart', 'route-config', 'lib/app_component.dart (RouteConfig for heroes)')(format=".")
:marked :marked
`@RouteConfig` takes a list of *route definitions*. `@RouteConfig` takes a list of *route definitions*.
We have only one route definition at the moment but rest assured, we'll add more. We have only one route definition at the moment but rest assured, we'll add more.
@ -202,7 +202,7 @@ code-example(language="bash").
We add an anchor tag to the template which, when clicked, triggers navigation to the `HeroesComponent`. We add an anchor tag to the template which, when clicked, triggers navigation to the `HeroesComponent`.
The revised template looks like this: The revised template looks like this:
+makeExample('toh-5/dart/lib/app_component_2.dart', 'template', 'app_component.dart (template for Heroes)')(format=".") +makeExample('toh-5/dart/lib/app_component_2.dart', 'template', 'lib/app_component.dart (template v1)')(format=".")
:marked :marked
Notice the `[routerLink]` binding in the anchor tag. Notice the `[routerLink]` binding in the anchor tag.
We bind the `RouterLink` directive (another of the `ROUTER_DIRECTIVES`) to a list We bind the `RouterLink` directive (another of the `ROUTER_DIRECTIVES`) to a list
@ -249,7 +249,7 @@ code-example(language="bash").
Import the `DashboardComponent` so we can reference it in the dashboard route definition. Import the `DashboardComponent` so we can reference it in the dashboard route definition.
Add the following `'Dashboard'` route definition to the `@RouteConfig` list of definitions. Add the following `'Dashboard'` route definition to the `@RouteConfig` list of definitions.
+makeExample('toh-5/dart/lib/app_component.dart','dashboard-route', 'app_component.dart (Dashboard Route)')(format=".") +makeExample('toh-5/dart/lib/app_component.dart','dashboard-route', 'lib/app_component.dart (Dashboard route)')(format=".")
.l-sub-section .l-sub-section
:marked :marked
**useAsDefault** **useAsDefault**
@ -264,7 +264,7 @@ code-example(language="bash").
:marked :marked
Finally, add a dashboard navigation link to the template, just above the *Heroes* link. Finally, add a dashboard navigation link to the template, just above the *Heroes* link.
+makeExample('toh-5/dart/lib/app_component.dart','template', 'app_component.dart (template)')(format=".") +makeExample('toh-5/dart/lib/app_component.dart','template', 'lib/app_component.dart (template)')(format=".")
.l-sub-section .l-sub-section
:marked :marked
We nestled the two links within `<nav>` tags. We nestled the two links within `<nav>` tags.
@ -282,10 +282,12 @@ code-example(language="bash").
+makeExample('toh-5/dart/lib/dashboard_component.dart', 'template-url', 'lib/dashboard_component.dart (templateUrl)')(format=".") +makeExample('toh-5/dart/lib/dashboard_component.dart', 'template-url', 'lib/dashboard_component.dart (templateUrl)')(format=".")
.l-sub-section .l-sub-section
:marked :marked
We specify the path _all the way back to the application root_. Angular doesn't support module-relative paths. We specify the path _all the way back to the application root_ &mdash;
because Angular doesn't support relative paths _by default_.
We _can_ switch to [component-relative paths](../cookbook/component-relative-paths.html) if we prefer.
:marked :marked
Create that file with these contents: Create that file with these contents:
+makeExample('toh-5/dart/lib/dashboard_component.html', null, 'dashboard_component.html')(format=".") +makeExample('toh-5/dart/lib/dashboard_component.html', null, 'lib/dashboard_component.html')(format=".")
:marked :marked
We use `*ngFor` once again to iterate over a list of heroes and display their names. We use `*ngFor` once again to iterate over a list of heroes and display their names.
We added extra `<div>` elements to help with styling later in this chapter. We added extra `<div>` elements to help with styling later in this chapter.
@ -302,14 +304,13 @@ code-example(language="bash").
and added it to the `providers` list of the top level `AppComponent`. and added it to the `providers` list of the top level `AppComponent`.
That move created a singleton `HeroService` instance, available to *all* components of the application. That move created a singleton `HeroService` instance, available to *all* components of the application.
We'll inject and use it here in the `DashboardComponent` . Angular will inject `HeroService` and we'll use it here in the `DashboardComponent`.
### Get heroes ### Get heroes
Open the `dashboard_component.dart` and add the requisite `import` statements. Open the `dashboard_component.dart` and add the requisite `import` statements.
+makeExample('toh-5/dart/lib/dashboard_component_2.dart','imports', 'lib/dashboard_component.dart (imports)')(format=".") +makeExample('toh-5/dart/lib/dashboard_component_2.dart','imports', 'lib/dashboard_component.dart (imports)')(format=".")
:marked :marked
We need `OnInit` interface because we'll initialize the heroes in the `ngOnInit` method as we've done before. We need `OnInit` interface because we'll initialize the heroes in the `ngOnInit` method as we've done before.
We need the `Hero` and `HeroService` symbols in order to reference those types.
Now implement the `DashboardComponent` class like this: Now implement the `DashboardComponent` class like this:
+makeExample('toh-5/dart/lib/dashboard_component_2.dart','component', 'lib/dashboard_component.dart (class)') +makeExample('toh-5/dart/lib/dashboard_component_2.dart','component', 'lib/dashboard_component.dart (class)')
@ -361,7 +362,7 @@ code-example(format='').
### Configure a Route with a Parameter ### Configure a Route with a Parameter
Here's the *route definition* we'll use. Here's the *route definition* we'll use.
+makeExample('toh-5/dart/lib/app_component.dart','hero-detail-route', 'lib/app_component.dart (Route to HeroDetailComponent)')(format=".") +makeExample('toh-5/dart/lib/app_component.dart','hero-detail-route', 'lib/app_component.dart (route to HeroDetailComponent)')(format=".")
:marked :marked
The colon (:) in the path indicates that `:id` is a placeholder to be filled with a specific hero `id` The colon (:) in the path indicates that `:id` is a placeholder to be filled with a specific hero `id`
when navigating to the `HeroDetailComponent`. when navigating to the `HeroDetailComponent`.
@ -386,7 +387,7 @@ code-example(format='').
:marked :marked
## Revise the *HeroDetailComponent* ## Revise the *HeroDetailComponent*
Before we rewrite the `HeroDetailComponent`, let's remember what it looks like now: Before we rewrite the `HeroDetailComponent`, let's review what it looks like now:
+makeExample('toh-4/dart/lib/hero_detail_component.dart', null, 'lib/hero_detail_component.dart (current)') +makeExample('toh-4/dart/lib/hero_detail_component.dart', null, 'lib/hero_detail_component.dart (current)')
:marked :marked
@ -394,12 +395,12 @@ code-example(format='').
We will no longer receive the hero in a parent component property binding. We will no longer receive the hero in a parent component property binding.
The new `HeroDetailComponent` should take the `id` parameter from the router's `RouteParams` service The new `HeroDetailComponent` should take the `id` parameter from the router's `RouteParams` service
and use the `HeroService` to fetch the hero with that `id` from storage. and use the `HeroService` to fetch the hero with that `id`.
We need an import statement to reference the `RouteParams`. We need an import statement to reference the `RouteParams`.
+makeExample('toh-5/dart/lib/hero_detail_component.dart', 'import-route-params')(format=".") +makeExample('toh-5/dart/lib/hero_detail_component.dart', 'import-route-params')(format=".")
:marked :marked
We import the `HeroService`so we can fetch a hero`. We import the `HeroService`so we can fetch a hero.
+makeExample('toh-5/dart/lib/hero_detail_component.dart', 'import-hero-service')(format=".") +makeExample('toh-5/dart/lib/hero_detail_component.dart', 'import-hero-service')(format=".")
:marked :marked
We import the `OnInit` interface because we'll call the `HeroService` inside the `ngOnInit` component lifecycle hook. We import the `OnInit` interface because we'll call the `HeroService` inside the `ngOnInit` component lifecycle hook.
@ -455,13 +456,11 @@ code-example(format='').
:marked :marked
Here's the (nearly) finished `HeroDetailComponent`: Here's the (nearly) finished `HeroDetailComponent`:
+makeExample('toh-5/dart/lib/hero_detail_component.dart', 'v2', 'lib/hero_detail_component.dart (latest)')(format=".") +makeExample('toh-5/dart/lib/hero_detail_component.dart', 'v2', 'lib/hero_detail_component.dart (latest)')(format=".")
:marked
.l-main-section .l-main-section
:marked :marked
## Select a *Dashboard* Hero ## Select a *Dashboard* Hero
When a user selects a hero in the dashboard, the app should navigate to the `HeroDetailComponent` to view and edit the selected hero.. When a user selects a hero in the dashboard, the app should navigate to the `HeroDetailComponent` to view and edit the selected hero.
In the dashboard template we bound each hero's click event to the `gotoDetail` method, passing along the selected `hero` entity. In the dashboard template we bound each hero's click event to the `gotoDetail` method, passing along the selected `hero` entity.
+makeExample('toh-5/dart/lib/dashboard_component.html','click', 'lib/dashboard_component.html (click binding)')(format=".") +makeExample('toh-5/dart/lib/dashboard_component.html','click', 'lib/dashboard_component.html (click binding)')(format=".")
@ -484,7 +483,7 @@ code-example(format='').
+makeExample('toh-5/dart/lib/app_component.dart','hero-detail-route', 'lib/app_component.dart (hero detail route)')(format=".") +makeExample('toh-5/dart/lib/app_component.dart','hero-detail-route', 'lib/app_component.dart (hero detail route)')(format=".")
:marked :marked
The `DashboardComponent` doesn't have the router yet. We obtain it in the usual way: The `DashboardComponent` doesn't have the router yet. We obtain it in the usual way:
`import` the `router` reference and inject it in the constructor (along with the `HeroService`): import the `router` reference and inject it in the constructor (along with the `HeroService`):
+makeExample('toh-5/dart/lib/dashboard_component.dart','import-router', 'lib/dashboard_component.dart (excerpts)')(format=".") +makeExample('toh-5/dart/lib/dashboard_component.dart','import-router', 'lib/dashboard_component.dart (excerpts)')(format=".")
+makeExample('toh-5/dart/lib/dashboard_component.dart','ctor')(format=".") +makeExample('toh-5/dart/lib/dashboard_component.dart','ctor')(format=".")
@ -499,9 +498,7 @@ code-example(format='').
That component's current template exhibits a "master/detail" style with the list of heroes That component's current template exhibits a "master/detail" style with the list of heroes
at the top and details of the selected hero below. at the top and details of the selected hero below.
**[TODO: Add example, once it exists.]** +makeExample('toh-4/dart/lib/app_component.dart','template', 'lib/heroes_component.dart (current template)')(format=".")
// makeExample('toh-4/dart/lib/app_component.dart','template', 'lib/heroes_component.dart (current template)')(format=".")
:marked :marked
Delete the last line of the template with the `<my-hero-detail>` tags. Delete the last line of the template with the `<my-hero-detail>` tags.
@ -525,7 +522,7 @@ figure.image-display
### Format with the *UpperCasePipe* ### Format with the *UpperCasePipe*
Notice that the hero's name is displayed in CAPITAL LETTERS. That's the effect of the `UpperCasePipe` Notice that the hero's name is displayed in CAPITAL LETTERS. That's the effect of the `UpperCasePipe`
that we slipped into the interpolation binding. Look for it right after the pipe operator, ( | ). that we slipped into the interpolation binding. Look for it right after the pipe operator ( | ).
+makeExample('toh-5/dart/lib/heroes_component.html','pipe')(format=".") +makeExample('toh-5/dart/lib/heroes_component.html','pipe')(format=".")
:marked :marked
Pipes are a good way to format strings, currency amounts, dates and other display data. Pipes are a good way to format strings, currency amounts, dates and other display data.
@ -546,14 +543,19 @@ figure.image-display
1. *Cut-and-paste* the styles contents into a new `heroes_component.css` file. 1. *Cut-and-paste* the styles contents into a new `heroes_component.css` file.
1. *Set* the component metadata's `templateUrl` and `styleUrls` properties to refer to both files. 1. *Set* the component metadata's `templateUrl` and `styleUrls` properties to refer to both files.
The revised component data looks like this: Because the template for `HeroesComponent` no longer uses `HeroDetailComponent`
directly &mdash; instead using the router to _navigate_ to it &mdash; we can
remove `HeroDetailComponent` from the directives list. That
list is now empty, so we can remove the `directives` argument. The revised
`@Component` looks like this:
+makeExample('toh-5/dart/lib/heroes_component.dart', 'metadata', 'lib/heroes_component.dart (revised metadata)')(format=".") +makeExample('toh-5/dart/lib/heroes_component.dart', 'metadata', 'lib/heroes_component.dart (revised metadata)')(format=".")
:marked :marked
Now we can see what's going on as we update the component class along the same lines as the dashboard: Now we can see what's going on as we update the component class along the same lines as the dashboard:
1. Import the `router` 1. Import the `router`
1. Inject the `router` in the constructor (along with the `HeroService`) 1. Inject the `router` in the constructor (along with the `HeroService`)
1. Implement the `gotoDetail` method by calling the `router.navigate` method 1. Implement the `gotoDetail` method by calling the `router.navigate` method
with a two-part 'HeroDetail' *link parameters list*. with a two-part `HeroDetail` *link parameters list*.
Here's the revised component class: Here's the revised component class:
+makeExample('toh-5/dart/lib/heroes_component.dart', 'class', 'lib/heroes_component.dart (class)') +makeExample('toh-5/dart/lib/heroes_component.dart', 'class', 'lib/heroes_component.dart (class)')
@ -608,7 +610,7 @@ lib/dashboard_component.css`)
We cooperated by surrounding those links in `<nav>` tags. We cooperated by surrounding those links in `<nav>` tags.
Add a `app_component.css` file to the `app` folder with the following content. Add a `app_component.css` file to the `app` folder with the following content.
+makeExample('toh-5/dart/lib/app_component.css', 'css', 'lib/app_component.css (Navigation Styles)') +makeExample('toh-5/dart/lib/app_component.css', '', 'lib/app_component.css (navigation styles)')
.l-sub-section .l-sub-section
:marked :marked
**The *router-link-active* class** **The *router-link-active* class**
@ -627,11 +629,20 @@ lib/dashboard_component.css`)
We can also create styles at the *application level* outside of any component. We can also create styles at the *application level* outside of any component.
Our designers provided some basic styles to apply to elements across the entire app. Our designers provided some basic styles to apply to elements across the entire app.
Add the following to a new file named `styles.css` in the root folder. These correspond to the full set of master styles that we
+makeExample('toh-5/ts/styles.1.css', '', 'styles.css (App Styles)')(format=".") introduced earlier (see
[QuickStart, "Add some style"](../quickstart.html#!#add-some-style)).
Here is an excerpt.
+makeExample('toh-5/ts/styles.1.css', 'toh-excerpt', 'styles.css (app styles excerpt)')(format=".")
- var styles_css = 'https://raw.githubusercontent.com/angular/angular.io/master/public/docs/_examples/styles.css'
:marked :marked
Reference this stylesheet within the `index.html` in the traditional manner. Add a new file named `styles.css` in the root folder, if there isn't one already.
Ensure that it contains the [master styles given here](!{styles_css}).
If necessary, also edit `index.html` to refer to this stylesheet.
+makeExample('toh-5/ts/index.html','css', 'index.html (link ref)')(format=".") +makeExample('toh-5/ts/index.html','css', 'index.html (link ref)')(format=".")
:marked :marked
Look at the app now. Our dashboard, heroes, and navigation links are styling! Look at the app now. Our dashboard, heroes, and navigation links are styling!
@ -642,10 +653,11 @@ figure.image-display
.l-main-section .l-main-section
:marked :marked
## Application structure and code ## Application structure and code
p.
Review the sample source code [in the live example for this chapter](/resources/live-examples/toh-5/ts/plnkr.html). Review the sample source code in the #[+liveExampleLink2('', 'toh-5')] for this chapter.
Verify that we have the following structure: Verify that we have the following structure:
:marked
.filetree .filetree
.file angular2-tour-of-heroes .file angular2-tour-of-heroes
.children .children
@ -672,7 +684,6 @@ figure.image-display
.file index.html .file index.html
.file styles.css .file styles.css
.file pubspec.yaml .file pubspec.yaml
:marked
.l-main-section .l-main-section
:marked :marked
@ -681,15 +692,15 @@ figure.image-display
### The Road Behind ### The Road Behind
We travelled a great distance in this chapter We travelled a great distance in this chapter
- We added the Angular *Component Router* to navigate among different components. - We added the Angular *Component Router* to navigate among different components.
- We learned how to create router links to represent navigation menu items - We learned how to create router links to represent navigation menu items.
- We used router parameters to navigate to the details of user selected hero - We used router parameters to navigate to the details of user selected hero.
- We shared the `HeroService` among multiple components - We shared the `HeroService` among multiple components.
- We moved HTML and CSS out of the component file and into their own files. - We moved HTML and CSS out of the component file and into their own files.
- We added the `uppercase` pipe to format data - We added the `uppercase` pipe to format data.
### The Road Ahead ### The Road Ahead
We have much of the foundation we need to build an application. We have much of the foundation we need to build an application.
We're still missing a key piece: remote data access. We're still missing a key piece: remote data access.
In a forthcoming tutorial chapter, In the next chapter,
well replace our mock data with data retrieved from a server using http. well replace our mock data with data retrieved from a server using http.

View File

@ -87,20 +87,22 @@ code-example(language="bash").
我们继续构建《英雄指南》,应用也会保持运行并自动更新。 我们继续构建《英雄指南》,应用也会保持运行并自动更新。
## Action plan ## Action plan
## 行动计划 ## 行动计划
Here's our plan
下面是我们的计划 Here's our plan:
* turn `AppComponent` into an application shell that only handles navigation, 下面是我们的计划:
* Turn `AppComponent` into an application shell that only handles navigation
* 把`AppComponent`变成应用程序的“壳”,它只处理导航, * 把`AppComponent`变成应用程序的“壳”,它只处理导航,
* relocate the *Heroes* concerns within the current `AppComponent` to a separate `HeroesComponent`, * Relocate the *Heroes* concerns within the current `AppComponent` to a separate `HeroesComponent`
* 把现在由`AppComponent`关注的*英雄们*移到一个独立的`HeroesComponent`中, * 把现在由`AppComponent`关注的*英雄们*移到一个独立的`HeroesComponent`中,
* add routing, * Add routing
* 添加路由 * 添加路由
* create a new `DashboardComponent`, * Create a new `DashboardComponent`
* 添加一个新的`DashboardComponent`组件 * 添加一个新的`DashboardComponent`组件
* tie the *Dashboard* into the navigation structure. * Tie the *Dashboard* into the navigation structure
* 把*仪表盘*加入导航结构中。 * 把*仪表盘*加入导航结构中。
.l-sub-section .l-sub-section
@ -137,15 +139,15 @@ code-example(language="bash").
`AppComponent`的职责已经被移交给`HeroesComponent`了。 `AppComponent`的职责已经被移交给`HeroesComponent`了。
与其把`AppComponent`中所有的东西都搬过去,不如索性把它改名为`HeroesComponent`,然后单独创建一个新的`AppComponent`壳。 与其把`AppComponent`中所有的东西都搬过去,不如索性把它改名为`HeroesComponent`,然后单独创建一个新的`AppComponent`壳。
The steps are: The steps are to rename:
步骤如下: 改名的步骤如下:
* rename `app.component.ts` file to `heroes.component.ts`. * `app.component.ts` file to `heroes.component.ts`
* 把`app.component.ts`文件改名为`heroes.component.ts` * 把`app.component.ts`文件改名为`heroes.component.ts`
* rename the `AppComponent` class to `HeroesComponent`. * `AppComponent` class to `HeroesComponent`
* 把`AppComponent`类改名为`HeroesComponent` * 把`AppComponent`类改名为`HeroesComponent`
* rename the selector `my-app` to `my-heroes`. * Selector `my-app` to `my-heroes`
* 把`my-app`选择器改名为`my-heroes` * 把`my-app`选择器改名为`my-heroes`
:marked :marked
+makeExample('toh-5/ts/app/heroes.component.ts', 'heroes-component-renaming', 'app/heroes.component.ts (showing renamings only)')(format=".") +makeExample('toh-5/ts/app/heroes.component.ts', 'heroes-component-renaming', 'app/heroes.component.ts (showing renamings only)')(format=".")
@ -934,17 +936,15 @@ figure.image-display
1. *Set* the component metadata's `templateUrl` and `styleUrls` properties to refer to both files. 1. *Set* the component metadata's `templateUrl` and `styleUrls` properties to refer to both files.
1. *设置*组件元数据的`templateUrl`和`styleUrls`属性,来分别引用这两个文件。 1. *设置*组件元数据的`templateUrl`和`styleUrls`属性,来分别引用这两个文件。
We no longer display the `HeroDetailComponent` in the `HeroesComponent` template because we're navigating to it. Because the template for `HeroesComponent` no longer uses `HeroDetailComponent`
So we can remove it from the metadata `directives` array. The `directives` array is now empty so we delete it. directly &mdash; instead using the router to _navigate_ to it &mdash; we can
We might as well delete the `HeroDetailComponent` import statement too. remove `HeroDetailComponent` from the directives list. That
list is now empty, so we can remove the `directives` property. The revised
`@Component` looks like this:
在`HeroesComponent`模板中,不需要再显示`HeroDetailComponent`,因为我们要导航到它。 由于`HeroesComponent`的模板中不再直接使用`HeroDetailComponent`而是通过路由_导航_到它
所以我们可以从元数据的`directives`数组中移除它。`directives`数组现在没东西了,因此我们也把它删掉。 于是我们就可以从`HeroDetailComponent`的指令列表中把它移除了。指令列表现在是空的,所以我们干脆把`directives`属性也移除。
我们也同样可以删掉`import` `HeroDetailComponent`的语句。 修改过的`@Component`看起来像这样:
The revised `@Component` looks like this:
修改过的`@Component`是这样的:
+makeExample('toh-5/ts/app/heroes.component.ts', 'metadata', 'app/heroes.component.ts (revised metadata)')(format=".") +makeExample('toh-5/ts/app/heroes.component.ts', 'metadata', 'app/heroes.component.ts (revised metadata)')(format=".")
:marked :marked
@ -1104,9 +1104,9 @@ figure.image-display
如果在根目录下没有一个名叫`styles.css`的文件,就添加它。 如果在根目录下没有一个名叫`styles.css`的文件,就添加它。
确保它包含[这里给出的主样式](!{styles_css})。 确保它包含[这里给出的主样式](!{styles_css})。
Also ensure this stylesheet is referenced in the traditional manner within `index.html`. If necessary, also edit `index.html` to refer to this stylesheet.
同时确保这个样式表在`index.html`中被使用传统方式引用了 如有必要,也可以编辑`index.html`来引用这个样式表
+makeExample('toh-5/ts/index.html','css', 'index.html (link ref)')(format=".") +makeExample('toh-5/ts/index.html','css', 'index.html (link ref)')(format=".")
:marked :marked
@ -1124,7 +1124,7 @@ figure.image-display
## 应用结构和代码 ## 应用结构和代码
p. p.
Review the sample source code in the #[+liveExampleLink2('', 'toh-5')] for this part. Review the sample source code in the #[+liveExampleLink2('', 'toh-5')] for this chapter.
Verify that we have the following structure: Verify that we have the following structure:
p. p.

View File

@ -51,6 +51,9 @@ module.exports = new Package('angular.io', [basePackage, targetPackage, cheatshe
'___esModule', '___esModule',
'___core_private_types__', '___core_private_types__',
'___platform_browser_private__', '___platform_browser_private__',
'___platform_browser_private_types__',
'___platform_browser_dynamic_private__',
'___platform_browser_dynamic_private_types__',
'___compiler_private__', '___compiler_private__',
'__core_private__', '__core_private__',
'___core_private__' '___core_private__'