From 35b54383c227781640e151c13f21a5ee68ff462e Mon Sep 17 00:00:00 2001 From: Patrice Chalin Date: Fri, 12 Aug 2016 13:39:17 -0700 Subject: [PATCH] docs(toh-5): add file to cache (#2102) * toh-pt5: cached version before new router was introduced * toh-pt5: refreshed cached copy from latest (post-RC5) --- public/docs/ts/_cache/tutorial/toh-pt5.jade | 740 ++++++++++++++++++++ scripts/cache.sh | 1 + 2 files changed, 741 insertions(+) create mode 100644 public/docs/ts/_cache/tutorial/toh-pt5.jade diff --git a/public/docs/ts/_cache/tutorial/toh-pt5.jade b/public/docs/ts/_cache/tutorial/toh-pt5.jade new file mode 100644 index 0000000000..60954ae6e1 --- /dev/null +++ b/public/docs/ts/_cache/tutorial/toh-pt5.jade @@ -0,0 +1,740 @@ +include ../_util-fns + +:marked + # Routing Around the App + We received new requirements for our Tour of Heroes application: + * Add a *Dashboard* view. + * Navigate between the *Heroes* and *Dashboard* views. + * 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; + + When we’re done, users will be able to navigate the app like this: +figure.image-display + img(src='/resources/images/devguide/toh/nav-diagram.png' alt="View navigations") +:marked + We'll add Angular’s *Component Router* to our app to satisfy these requirements. +.l-sub-section + :marked + The [Routing and Navigation](../guide/router.html) chapter covers the router in more detail + than we will in this tutorial. + +:marked + Run the for this part. + +.l-sub-section + img(src='/resources/images/devguide/plunker-separate-window-button.png' alt="pop out the window" align="right" style="margin-right:-20px") + :marked + To see the URL changes in the browser address bar, + pop out the preview window by clicking the blue 'X' button in the upper right corner: + +.l-main-section +:marked + ## Where We Left Off + Before we continue with our Tour of Heroes, let’s verify that we have the following structure after adding our hero service + and hero detail component. If not, we’ll need to go back and follow the previous chapters. + +.filetree + .file angular2-tour-of-heroes + .children + .file app + .children + .file app.component.ts + .file app.module.ts + .file hero.ts + .file hero-detail.component.ts + .file hero.service.ts + .file main.ts + .file mock-heroes.ts + .file node_modules ... + .file typings ... + .file index.html + .file package.json + .file styles.css + .file systemjs.config.js + .file tsconfig.json + .file typings.json +:marked + ### Keep the app transpiling and running + Open a terminal/console window and enter the following command to + start the TypeScript compiler, start the server, and watch for changes: + +code-example(language="bash"). + npm start + +:marked + The application runs and updates automatically as we continue to build the Tour of Heroes. + + ## Action plan + Here's our plan: + + * Turn `AppComponent` into an application shell that only handles navigation + * Relocate the *Heroes* concerns within the current `AppComponent` to a separate `HeroesComponent` + * Add routing + * Create a new `DashboardComponent` + * Tie the *Dashboard* into the navigation structure + +.l-sub-section + :marked + *Routing* is another name for *navigation*. The *router* is the mechanism for navigating from view to view. + +.l-main-section +:marked + ## Splitting the *AppComponent* + + Our current app loads `AppComponent` and immediately displays the list of heroes. + + Our revised app should present a shell with a choice of views (*Dashboard* and *Heroes*) and then default to one of them. + + The `AppComponent` should only handle navigation. + Let's move the display of *Heroes* out of `AppComponent` and into its own `HeroesComponent`. + + ### *HeroesComponent* + `AppComponent` is already dedicated to *Heroes*. + Instead of moving anything out of `AppComponent`, we'll just rename it `HeroesComponent` + and create a new `AppComponent` shell separately. + + The steps are to rename: + * `app.component.ts` file to `heroes.component.ts` + * `AppComponent` class to `HeroesComponent` + * Selector `my-app` to `my-heroes` + +:marked ++makeExample('toh-5/ts/app/heroes.component.ts', 'heroes-component-renaming', 'app/heroes.component.ts (showing renamings only)')(format=".") + +:marked + ## Create *AppComponent* + The new `AppComponent` will be the application shell. + It will have some navigation links at the top and a display area below for the pages we navigate to. + + The initial steps are: + + * create a new file named `app.component.ts`. + * define an `AppComponent` class. + * `export` it so we can reference it during bootstrapping in `app.module.ts`. + * expose an application `title` property. + * add the `@Component` metadata decorator above the class with a `my-app` selector. + * add a template with `

` tags surrounding a binding to the `title` property. + * add the `` tags to the template so we still see the heroes. + * add the `HeroesComponent` to the root NgModule's `declarations` array so Angular recognizes the `` tags. + * add the `HeroService` to the root NgModule's `providers` array because we'll need it in every other view. + * add the supporting `import` statements. + + Our first draft looks like this: ++makeTabs( + `toh-5/ts/app/app.component.1.ts, + toh-5/ts/app/app.module.1.ts`, + ',', + `app/app.component.ts (v1), + app/app.module.ts (v1)`) + +:marked +.callout.is-critical + header Remove HeroService from the HeroesComponent providers + :marked + Go back to the `HeroesComponent` and **remove the `HeroService`** from its `providers` array. + We are *promoting* this service from the `HeroesComponent` to the root `NgModule`. + We ***do not want two copies*** of this service at two different levels of our app. +:marked + The app still runs and still displays heroes. + Our refactoring of `AppComponent` into a new `AppComponent` and a `HeroesComponent` worked! + We have done no harm. + +:marked + ## Add Routing + + We're ready to take the next step. + Instead of displaying heroes automatically, we'd like to show them *after* the user clicks a button. + In other words, we'd like to navigate to the list of heroes. + + We'll need the Angular *Component Router*. + + ### Set the base tag + Open the `index.html` and add `` at the top of the `` section. ++makeExample('toh-5/ts/index.html', 'base-href', 'index.html (base href)')(format=".") +.callout.is-important + header base href is essential + :marked + See the *base href* section of the [Router](../guide/router.html#!#base-href) chapter to learn why this matters. +:marked + The Angular router is a combination of multiple provided services (`RouterModule`), multiple directives (`RouterOutlet, + RouterLink, RouterLinkActive`), and a configuration (`Routes`). We'll configure our routes first: + + ### Configure the routes + + The *Component Router* is an external, optional Angular NgModule called `RouterModule`. + + Our application doesn't have any routes yet. + Start by creating a configuration file for the application routes. + *Routes* tell the router which views to display when a user clicks a link or + pastes a URL into the browser address bar. + + Our first route goes to the `HeroesComponent`. ++makeExample('toh-5/ts/app/app.routing.1.ts', 'routing-config', 'app/app.routing.ts (heroes route)')(format=".") +:marked + The `Routes` are an array of *route definitions*. + We have only one route definition at the moment but rest assured, we'll add more. + + This *route definition* has two parts: + * **path**: the router matches this route's path to the URL in the browser address bar (`/heroes`). + + * **component**: the component that the router should create when navigating to this route (`HeroesComponent`). + +.l-sub-section + :marked + Learn more about defining routes with Routes in the [Routing](../guide/router.html) chapter. + +:marked + We'll export the `routing` constant using the **RouterModule.forRoot** method with our array of routes. + This returns a configured router module we'll add to our root NgModule, `AppModule`. + ++makeExample('toh-5/ts/app/app.routing.1.ts', 'routing-export', 'app/app.routing.ts (routing export)')(format=".") +.l-sub-section + :marked + We call the `forRoot` method because we're providing a configured router at the _root_ of the application. + The `forRoot` method gives us the Router service providers and directives needed for routing. + +:marked + ### Make the router available. + We've setup our initial routes in our `app.routing.ts` file. Now we'll add it to our root NgModule. + + We'll import our `routing` constant from our `app.routing.ts` file and add it root NgModule's `imports` array. + + We'll also import our `HeroesComponent` and add it to our `declarations` array. + ++makeExample('toh-5/ts/app/app.module.2.ts', '', 'app/app.module.ts')(format=".") + +:marked + ### Router Outlet + + If we paste the path, `/heroes`, into the browser address bar, + the router should match it to the `heroes` route and display the `HeroesComponent`. + But where? + + We have to ***tell it where*** by adding `` marker tags to the bottom of the template. + `RouterOutlet` is one of the directives provided by the `RouterModule`. + The router displays each component immediately below the `` as we navigate through the application. + + ### Router Links + We don't really expect users to paste a route URL into the address bar. + We add an anchor tag to the template which, when clicked, triggers navigation to the `HeroesComponent`. + + The revised template looks like this: ++makeExample('toh-5/ts/app/app.component.2.ts', 'template', 'app/app.component.ts (template v1)')(format=".") +:marked + Notice the `routerLink` binding in the anchor tag. + We bind the `RouterLink` directive (another of the `RouterModule` directives) to a string + that tells the router where to navigate when the user clicks the link. + + Since our link is not dynamic, we define a *routing instruction* with a **one-time binding** to our route **path**. + Looking back at the route configuration, we confirm that `'/heroes'` is the path of the route to the `HeroesComponent`. +.l-sub-section + :marked + For more dynamic router links, learn about the *link parameters array* in the [Routing](../guide/router.html#link-parameters-array) chapter. +:marked + Refresh the browser. We see only the app title. We don't see the heroes list. +.l-sub-section + :marked + The browser's address bar shows `/`. + The route path to `HeroesComponent` is `/heroes`, not `/`. + We don't have a route that matches the path `/`, so there is nothing to show. + That's something we'll want to fix. +:marked + We click the "Heroes" navigation link, the browser bar updates to `/heroes`, + and now we see the list of heroes. We are navigating at last! + + At this stage, our `AppComponent` looks like this. ++makeExample('toh-5/ts/app/app.component.2.ts',null, 'app/app.component.ts (v2)') +:marked + The *AppComponent* is now attached to a router and displaying routed views. + For this reason and to distinguish it from other kinds of components, + we call this type of component a *Router Component*. + + +:marked + ## Add a *Dashboard* + Routing only makes sense when we have multiple views. We need another view. + + Create a placeholder `DashboardComponent` that gives us something to navigate to and from. ++makeExample('toh-5/ts/app/dashboard.component.1.ts',null, 'app/dashboard.component.ts (v1)')(format=".") +:marked + We’ll come back and make it more useful later. + + ### Configure the dashboard route + Go back to `app.routing.ts` and teach it to navigate to the dashboard. + + Import the `DashboardComponent` so we can reference it in the dashboard route definition. + + Add the following `'Dashboard'` route definition to the `Routes` array of definitions. ++makeExample('toh-5/ts/app/app.routing.2.ts','dashboard-route', 'app/app.routing.ts (Dashboard route)')(format=".") + +:marked + We also need to add the `DashboardComponent` to our root NgModule's `declarations`. + ++makeExample('toh-5/ts/app/app.module.3.ts','dashboard-declaration', 'app/app.module.ts (Dashboard declaration)')(format=".") + +.l-sub-section + :marked + **Redirect** + + We want the app to show the dashboard when it starts and + we want to see a nice URL in the browser address bar that says `/dashboard`. + Remember that the browser launches with `/` in the address bar. + We can use a redirect route to make this happen. + ++makeExample('toh-5/ts/app/app.routing.2.ts','redirect-route', 'app/app.routing.ts (Redirect route)')(format=".") + +.l-sub-section + :marked + Learn about the *redirects* in the [Routing](../guide/router.html#!#redirect) chapter. + +:marked + Finally, add a dashboard navigation link to the template, just above the *Heroes* link. + ++makeExample('toh-5/ts/app/app.component.3.ts','template', 'app/app.component.ts (template)')(format=".") +.l-sub-section + :marked + We nestled the two links within `