diff --git a/public/docs/_examples/toh-5/ts/app/app-routing.module.ts b/public/docs/_examples/toh-5/ts/app/app-routing.module.ts new file mode 100644 index 0000000000..dfd957782b --- /dev/null +++ b/public/docs/_examples/toh-5/ts/app/app-routing.module.ts @@ -0,0 +1,20 @@ +// #docregion +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { DashboardComponent } from './dashboard.component'; +import { HeroesComponent } from './heroes.component'; +import { HeroDetailComponent } from './hero-detail.component'; + +const routes: Routes = [ + { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, + { path: 'dashboard', component: DashboardComponent }, + { path: 'detail/:id', component: HeroDetailComponent }, + { path: 'heroes', component: HeroesComponent } +]; + +@NgModule({ + imports: [ RouterModule.forRoot(routes) ], + exports: [ RouterModule ] +}) +export class AppRoutingModule {} diff --git a/public/docs/_examples/toh-5/ts/app/app.module.ts b/public/docs/_examples/toh-5/ts/app/app.module.ts index 1503ac53c7..b376d69aba 100644 --- a/public/docs/_examples/toh-5/ts/app/app.module.ts +++ b/public/docs/_examples/toh-5/ts/app/app.module.ts @@ -1,9 +1,7 @@ -// #docplaster // #docregion import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; -import { RouterModule } from '@angular/router'; import { AppComponent } from './app.component'; import { DashboardComponent } from './dashboard.component'; @@ -11,44 +9,27 @@ import { HeroDetailComponent } from './hero-detail.component'; import { HeroesComponent } from './heroes.component'; import { HeroService } from './hero.service'; +// #docregion routing-module +import { AppRoutingModule } from './app-routing.module'; + @NgModule({ imports: [ BrowserModule, FormsModule, - RouterModule.forRoot([ - { - path: '', - redirectTo: '/dashboard', - pathMatch: 'full' - }, - { - path: 'dashboard', - component: DashboardComponent - }, - { - path: 'detail/:id', - component: HeroDetailComponent - }, - { - path: 'heroes', - component: HeroesComponent - } - ]) + AppRoutingModule ], - // #enddocregion routing - // #docregion dashboard, hero-detail +// #enddocregion routing-module + // #docregion dashboard declarations: [ AppComponent, DashboardComponent, HeroDetailComponent, HeroesComponent ], - // #enddocregion dashboard, hero-detail - providers: [ - HeroService - ], + // #enddocregion dashboard + providers: [ HeroService ], bootstrap: [ AppComponent ] - // #docregion routing +// #docregion routing-module }) -export class AppModule { -} +export class AppModule { } +// #enddocregion routing-module diff --git a/public/docs/_examples/toh-6/ts/app/app-routing.module.ts b/public/docs/_examples/toh-6/ts/app/app-routing.module.ts new file mode 100644 index 0000000000..bc070f6c31 --- /dev/null +++ b/public/docs/_examples/toh-6/ts/app/app-routing.module.ts @@ -0,0 +1,19 @@ +import { NgModule } from '@angular/core'; +import { RouterModule, Routes } from '@angular/router'; + +import { DashboardComponent } from './dashboard.component'; +import { HeroesComponent } from './heroes.component'; +import { HeroDetailComponent } from './hero-detail.component'; + +const routes: Routes = [ + { path: '', redirectTo: '/dashboard', pathMatch: 'full' }, + { path: 'dashboard', component: DashboardComponent }, + { path: 'detail/:id', component: HeroDetailComponent }, + { path: 'heroes', component: HeroesComponent } +]; + +@NgModule({ + imports: [ RouterModule.forRoot(routes) ], + exports: [ RouterModule ] +}) +export class AppRoutingModule {} diff --git a/public/docs/_examples/toh-6/ts/app/app.module.ts b/public/docs/_examples/toh-6/ts/app/app.module.ts index a4efc4b34d..8ddf858972 100644 --- a/public/docs/_examples/toh-6/ts/app/app.module.ts +++ b/public/docs/_examples/toh-6/ts/app/app.module.ts @@ -9,11 +9,12 @@ import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { FormsModule } from '@angular/forms'; import { HttpModule } from '@angular/http'; -import { RouterModule } from '@angular/router'; + +import { AppRoutingModule } from './app-routing.module'; // #enddocregion v1 // Imports for loading & configuring the in-memory web api -import { InMemoryWebApiModule } from 'angular-in-memory-web-api'; +import { InMemoryWebApiModule } from 'angular-in-memory-web-api/in-memory-web-api.module'; import { InMemoryDataService } from './in-memory-data.service'; // #docregion v1 @@ -36,25 +37,7 @@ import { HeroSearchComponent } from './hero-search.component'; InMemoryWebApiModule.forRoot(InMemoryDataService), // #enddocregion in-mem-web-api // #docregion v1 - RouterModule.forRoot([ - { - path: '', - redirectTo: '/dashboard', - pathMatch: 'full' - }, - { - path: 'dashboard', - component: DashboardComponent - }, - { - path: 'detail/:id', - component: HeroDetailComponent - }, - { - path: 'heroes', - component: HeroesComponent - } - ]) + AppRoutingModule ], // #docregion search declarations: [ @@ -67,10 +50,7 @@ import { HeroSearchComponent } from './hero-search.component'; // #docregion v1, v2 ], // #enddocregion search - providers: [ - HeroService, - ], + providers: [ HeroService ], bootstrap: [ AppComponent ] }) -export class AppModule { -} +export class AppModule { } diff --git a/public/docs/ts/latest/tutorial/toh-pt5.jade b/public/docs/ts/latest/tutorial/toh-pt5.jade index 4101aa4646..33e3d294f5 100644 --- a/public/docs/ts/latest/tutorial/toh-pt5.jade +++ b/public/docs/ts/latest/tutorial/toh-pt5.jade @@ -644,17 +644,67 @@ block extract-id Refresh the browser and select a hero from the dashboard; the app should navigate directly to that hero’s details. .l-main-section +:marked + ## Refactor routes to a _Routing Module_ + + Almost 20 lines of `AppModule` are devoted to configuring four routes. + Most application have many more routes and they [add guard services](../guide/router.html#guards) + to protect against unwanted or unauthorized navigations. + Routing considerations could quickly dominate this module and obscure its primary purpose which is to + establish key facts about the entire app for the Angular compiler. + + We should refactor the routing configuration into its own class. + What kind of class? + The current `RouterModule.forRoot()` produces an Angular `ModuleWithProviders` which suggests that a + class dedicated to routing should be some kind of module. + It should be a [_Routing Module_](../guide/router.htm#routing-module). + + By convention the name of a _Routing Module_ contains the word "Routing" and + aligns with the name of the module that declares the components navigated to". + + Create an `app-routing.module.ts` file as a sibling to `app.module.ts`. Give it the following contents extracted from the `AppModule` class: + ++makeExample('app/app-routing.module.ts') +:marked + Noteworthy points, typical of _Routing Modules_: + * Pull the routes into a variable. You might export it in future and it clarifies the _Routing Module_ pattern. + + * Add `RouterModule.forRoot(routes)` to `imports`. + + * Add `RouterModule` to `exports` so that the components in the companion module have access to Router declarables + such as `RouterLink` and `RouterOutlet`. + + * No `declarations`! Declarations are the responsibility of the companion module. + + * Add module `providers` for guard services if you have them; there are none in this example. + + ### Update _AppModule_ + + Now delete the routing configuration from `AppModule` and import the `AppRoutingModule` + (_both_ with an ES `import` statement _and_ by adding it to the `NgModule.imports` list). + + Here is the revised `AppModule`, compared to its pre-refactor state: ++makeTabs( + `toh-5/ts/app/app.module.ts, toh-5/ts/app/app.module.3.ts`, + null, + `app/app.module.ts (after), app/app.module.ts (before)`) +:marked + It's simpler and focused on indentifying the key pieces of the application. +.l-main-section :marked ## Select a Hero in the *HeroesComponent* + Earlier we added the ability to select a hero from the dashboard. We'll do something similar in the `HeroesComponent`. - That component's current template exhibits a "master/detail" style with the list of heroes + The `HeroesComponent` template exhibits a "master/detail" style with the list of heroes at the top and details of the selected hero below. +makeExample('toh-4/ts/app/app.component.ts','template', 'app/heroes.component.ts (current template)')(format=".") :marked + Our goal is to move the detail to its own view and navigate to it when the user decides to edit a selected hero. + Delete the `

` at the top (forgot about it during the `AppComponent`-to-`HeroesComponent` conversion). Delete the last line of the template with the `` tags. @@ -663,8 +713,9 @@ block extract-id We're going to display the hero detail on its own page and route to it as we did in the dashboard. But we'll throw in a small twist for variety. - When the user selects a hero from the list, we *won't* go to the detail page. - We'll show a *mini-detail* on *this* page instead and make the user click a button to navigate to the *full detail *page. + We are keeping the "master/detail" style but shrinking the detail to a "mini", read-only version. + When the user selects a hero from the list, we *don't* go to the detail page. + We show a *mini-detail* on *this* page instead and make the user click a button to navigate to the *full detail *page. ### Add the *mini-detail* @@ -859,6 +910,7 @@ block file-tree-end .file app.component.css .file app.component.ts .file app.module.ts + .file app-routing.module.ts .file dashboard.component.css .file dashboard.component.html .file dashboard.component.ts @@ -895,6 +947,7 @@ block file-tree-end - We shared the `HeroService` among multiple components. - We moved HTML and CSS out of the component file and into their own files. - We added the `uppercase` pipe to format data. + - We refactored routes into a `Routing Module` that we import. ### The Road Ahead diff --git a/public/docs/ts/latest/tutorial/toh-pt6.jade b/public/docs/ts/latest/tutorial/toh-pt6.jade index f34bfbb9f1..fac7513ff5 100644 --- a/public/docs/ts/latest/tutorial/toh-pt6.jade +++ b/public/docs/ts/latest/tutorial/toh-pt6.jade @@ -584,7 +584,7 @@ block filetree - We configured an in-memory web API. - We learned how to use !{_Observable}s. - Here are the files we added or changed in this chapter. + Here are the files we _added or changed_ in this chapter. block file-summary +makeTabs(