5 lines
53 KiB
JSON
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"id": "tutorial/toh-pt5",
"title": "Add navigation with routing",
"contents": "\n\n\n<div class=\"github-links\">\n <a href=\"https://github.com/angular/angular/edit/master/aio/content/tutorial/toh-pt5.md?message=docs%3A%20describe%20your%20change...\" aria-label=\"Suggest Edits\" title=\"Suggest Edits\"><i class=\"material-icons\" aria-hidden=\"true\" role=\"img\">mode_edit</i></a>\n</div>\n\n\n<div class=\"content\">\n <h1 id=\"add-navigation-with-routing\">Add navigation with routing<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#add-navigation-with-routing\"><i class=\"material-icons\">link</i></a></h1>\n<p>There are new requirements for the Tour of Heroes app:</p>\n<ul>\n<li>Add a <em>Dashboard</em> view.</li>\n<li>Add the ability to navigate between the <em>Heroes</em> and <em>Dashboard</em> views.</li>\n<li>When users click a hero name in either view, navigate to a detail view of the selected hero.</li>\n<li>When users click a <em>deep link</em> in an email, open the detail view for a particular hero.</li>\n</ul>\n<div class=\"alert is-helpful\">\n<p> For the sample application that this page describes, see the <live-example></live-example>.</p>\n</div>\n<p>When youre done, users will be able to navigate the application like this:</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/toh/nav-diagram.png\" alt=\"View navigations\" width=\"506\" height=\"433\">\n</div>\n<h2 id=\"add-the-approutingmodule\">Add the <code>AppRoutingModule</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#add-the-approutingmodule\"><i class=\"material-icons\">link</i></a></h2>\n<p>In Angular, the best practice is to load and configure the router in a separate, top-level module\nthat is dedicated to routing and imported by the root <code>AppModule</code>.</p>\n<p>By convention, the module class name is <code>AppRoutingModule</code> and it belongs in the <code>app-routing.module.ts</code> in the <code>src/app</code> folder.</p>\n<p>Use the CLI to generate it.</p>\n<code-example language=\"sh\" class=\"code-shell\">\n ng generate module app-routing --flat --module=app\n</code-example>\n<div class=\"alert is-helpful\">\n<p><code>--flat</code> puts the file in <code>src/app</code> instead of its own folder.<br>\n<code>--module=app</code> tells the CLI to register it in the <code>imports</code> array of the <code>AppModule</code>.</p>\n</div>\n<p>The generated file looks like this:</p>\n<code-example path=\"toh-pt5/src/app/app-routing.module.0.ts\" header=\"src/app/app-routing.module.ts (generated)\">\nimport { <a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a> } from '@angular/core';\nimport { <a href=\"api/common/CommonModule\" class=\"code-anchor\">CommonModule</a> } from '@angular/common';\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n <a href=\"api/common/CommonModule\" class=\"code-anchor\">CommonModule</a>\n ],\n declarations: []\n})\nexport class AppRoutingModule { }\n\n\n</code-example>\n<p>Replace it with the following:</p>\n<code-example path=\"toh-pt5/src/app/app-routing.module.1.ts\" header=\"src/app/app-routing.module.ts (updated)\">\nimport { <a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a> } from '@angular/core';\nimport { <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>, <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> } from '@angular/router';\nimport { HeroesComponent } from './heroes/heroes.component';\n\nconst routes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'heroes', component: HeroesComponent }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [RouterModule.forRoot(routes)],\n exports: [<a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>]\n})\nexport class AppRoutingModule { }\n\n\n</code-example>\n<p>First, the <code>app-routing.module.ts</code> file imports <code><a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a></code> and <code><a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a></code> so the application can have routing functionality. The next import, <code>HeroesComponent</code>, will give the Router somewhere to go once you configure the routes.</p>\n<p>Notice that the <code><a href=\"api/common/CommonModule\" class=\"code-anchor\">CommonModule</a></code> references and <code>declarations</code> array are unnecessary, so are no\nlonger part of <code>AppRoutingModule</code>. The following sections explain the rest of the <code>AppRoutingModule</code> in more detail.</p>\n<h3 id=\"routes\">Routes<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#routes\"><i class=\"material-icons\">link</i></a></h3>\n<p>The next part of the file is where you configure your routes.\n<em>Routes</em> tell the Router which view to display when a user clicks a link or\npastes a URL into the browser address bar.</p>\n<p>Since <code>app-routing.module.ts</code> already imports <code>HeroesComponent</code>, you can use it in the <code>routes</code> array:</p>\n<code-example path=\"toh-pt5/src/app/app-routing.module.ts\" header=\"src/app/app-routing.module.ts\" region=\"heroes-route\">\n\nconst routes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'heroes', component: HeroesComponent }\n];\n\n</code-example>\n<p>A typical Angular <code><a href=\"api/router/Route\" class=\"code-anchor\">Route</a></code> has two properties:</p>\n<ul>\n<li><code>path</code>: a string that matches the URL in the browser address bar.</li>\n<li><code>component</code>: the component that the router should create when navigating to this route.</li>\n</ul>\n<p>This tells the router to match that URL to <code>path: 'heroes'</code>\nand display the <code>HeroesComponent</code> when the URL is something like <code>localhost:4200/heroes</code>.</p>\n<h3 id=\"routermoduleforroot\"><code><a href=\"api/router/RouterModule#forRoot\" class=\"code-anchor\">RouterModule.forRoot()</a></code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#routermoduleforroot\"><i class=\"material-icons\">link</i></a></h3>\n<p>The <code>@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a></code> metadata initializes the router and starts it listening for browser location changes.</p>\n<p>The following line adds the <code><a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a></code> to the <code>AppRoutingModule</code> <code>imports</code> array and\nconfigures it with the <code>routes</code> in one step by calling\n<code><a href=\"api/router/RouterModule#forRoot\" class=\"code-anchor\">RouterModule.forRoot()</a></code>:</p>\n<code-example path=\"toh-pt5/src/app/app-routing.module.ts\" header=\"src/app/app-routing.module.ts\" region=\"ngmodule-imports\">\nimports: [ RouterModule.forRoot(routes) ],\n\n</code-example>\n<div class=\"alert is-helpful\">\n<p> The method is called <code>forRoot()</code> because you configure the router at the application's root level.\nThe <code>forRoot()</code> method supplies the service providers and directives needed for routing,\nand performs the initial navigation based on the current browser URL.</p>\n</div>\n<p>Next, <code>AppRoutingModule</code> exports <code><a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a></code> so it will be available throughout the app.</p>\n<code-example path=\"toh-pt5/src/app/app-routing.module.ts\" header=\"src/app/app-routing.module.ts (exports array)\" region=\"export-routermodule\">\nexports: [ <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a> ]\n\n</code-example>\n<h2 id=\"add-routeroutlet\">Add <code><a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a></code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#add-routeroutlet\"><i class=\"material-icons\">link</i></a></h2>\n<p>Open the <code>AppComponent</code> template and replace the <code>&#x3C;app-heroes></code> element with a <code>&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></code> element.</p>\n<code-example path=\"toh-pt5/src/app/app.component.html\" region=\"outlet\" header=\"src/app/app.component.html (router-outlet)\">\n&#x3C;h1>{{title}}&#x3C;/h1>\n&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>&#x3C;/<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n&#x3C;app-messages>&#x3C;/app-messages>\n\n</code-example>\n<p>The <code>AppComponent</code> template no longer needs <code>&#x3C;app-heroes></code> because the application will only display the <code>HeroesComponent</code> when the user navigates to it.</p>\n<p>The <code>&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></code> tells the router where to display routed views.</p>\n<div class=\"alert is-helpful\">\n<p>The <code><a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a></code> is one of the router directives that became available to the <code>AppComponent</code>\nbecause <code>AppModule</code> imports <code>AppRoutingModule</code> which exported <code><a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a></code>. The <code>ng generate</code> command you ran at the start of this tutorial added this import because of the <code>--module=app</code> flag. If you manually created <code>app-routing.module.ts</code> or used a tool other than the CLI to do so, you'll need to import <code>AppRoutingModule</code> into <code>app.module.ts</code> and add it to the <code>imports</code> array of the <code><a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a></code>.</p>\n</div>\n<h4 id=\"try-it\">Try it<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#try-it\"><i class=\"material-icons\">link</i></a></h4>\n<p>You should still be running with this CLI command.</p>\n<code-example language=\"sh\" class=\"code-shell\">\n ng serve\n</code-example>\n<p>The browser should refresh and display the application title but not the list of heroes.</p>\n<p>Look at the browser's address bar.\nThe URL ends in <code>/</code>.\nThe route path to <code>HeroesComponent</code> is <code>/heroes</code>.</p>\n<p>Append <code>/heroes</code> to the URL in the browser address bar.\nYou should see the familiar heroes master/detail view.</p>\n<a id=\"routerlink\"></a>\n<h2 id=\"add-a-navigation-link-routerlink\">Add a navigation link (<code><a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a></code>)<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#add-a-navigation-link-routerlink\"><i class=\"material-icons\">link</i></a></h2>\n<p>Ideally, users should be able to click a link to navigate rather\nthan pasting a route URL into the address bar.</p>\n<p>Add a <code>&#x3C;nav></code> element and, within that, an anchor element that, when clicked,\ntriggers navigation to the <code>HeroesComponent</code>.\nThe revised <code>AppComponent</code> template looks like this:</p>\n<code-example path=\"toh-pt5/src/app/app.component.html\" region=\"heroes\" header=\"src/app/app.component.html (heroes RouterLink)\">\n&#x3C;h1>{{title}}&#x3C;/h1>\n&#x3C;nav>\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/heroes\">Heroes&#x3C;/a>\n&#x3C;/nav>\n&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>&#x3C;/<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n&#x3C;app-messages>&#x3C;/app-messages>\n\n</code-example>\n<p>A <a href=\"tutorial/toh-pt5#routerlink\"><code>routerLink</code> attribute</a> is set to <code>\"/heroes\"</code>,\nthe string that the router matches to the route to <code>HeroesComponent</code>.\nThe <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a></code> is the selector for the <a href=\"/api/router/RouterLink\"><code>RouterLink</code> directive</a>\nthat turns user clicks into router navigations.\nIt's another of the public directives in the <code><a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a></code>.</p>\n<p>The browser refreshes and displays the application title and heroes link,\nbut not the heroes list.</p>\n<p>Click the link.\nThe address bar updates to <code>/heroes</code> and the list of heroes appears.</p>\n<div class=\"alert is-helpful\">\n<p>Make this and future navigation links look better by adding private CSS styles to <code>app.component.css</code>\nas listed in the <a href=\"tutorial/toh-pt5#appcomponent\">final code review</a> below.</p>\n</div>\n<h2 id=\"add-a-dashboard-view\">Add a dashboard view<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#add-a-dashboard-view\"><i class=\"material-icons\">link</i></a></h2>\n<p>Routing makes more sense when there are multiple views.\nSo far there's only the heroes view.</p>\n<p>Add a <code>DashboardComponent</code> using the CLI:</p>\n<code-example language=\"sh\" class=\"code-shell\">\n ng generate component dashboard\n</code-example>\n<p>The CLI generates the files for the <code>DashboardComponent</code> and declares it in <code>AppModule</code>.</p>\n<p>Replace the default file content in these three files as follows:</p>\n<code-tabs>\n <code-pane header=\"src/app/dashboard/dashboard.component.html\" path=\"toh-pt5/src/app/dashboard/dashboard.component.1.html\">\n&#x3C;h2>Top Heroes&#x3C;/h2>\n&#x3C;div class=\"heroes-menu\">\n &#x3C;a *<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a>=\"let hero of heroes\">\n {{hero.name}}\n &#x3C;/a>\n&#x3C;/div>\n\n\n</code-pane>\n\n <code-pane header=\"src/app/dashboard/dashboard.component.ts\" path=\"toh-pt5/src/app/dashboard/dashboard.component.ts\">\nimport { <a href=\"api/core/Component\" class=\"code-anchor\">Component</a>, <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> } from '@angular/core';\nimport { Hero } from '../hero';\nimport { HeroService } from '../hero.service';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-dashboard',\n templateUrl: './dashboard.component.html',\n styleUrls: [ './dashboard.component.css' ]\n})\nexport class DashboardComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n heroes: Hero[] = [];\n\n constructor(private heroService: HeroService) { }\n\n ngOnInit() {\n this.getHeroes();\n }\n\n getHeroes(): void {\n this.heroService.getHeroes()\n .subscribe(heroes => this.heroes = heroes.slice(1, 5));\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"src/app/dashboard/dashboard.component.css\" path=\"toh-pt5/src/app/dashboard/dashboard.component.css\">\n/* DashboardComponent's private CSS styles */\n\nh2 {\n text-align: center;\n}\n\n.heroes-menu {\n padding: 0;\n margin: auto;\n max-width: 1000px;\n\n /* flexbox */\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: space-around;\n align-content: flex-start;\n align-items: flex-start;\n}\n\na {\n background-color: #3f525c;\n border-radius: 2px;\n padding: 1rem;\n font-size: 1.2rem;\n text-decoration: none;\n display: inline-block;\n color: #fff;\n text-align: center;\n width: 100%;\n min-width: 70px;\n margin: .5rem auto;\n box-sizing: border-box;\n\n /* flexbox */\n order: 0;\n flex: 0 1 auto;\n align-self: auto;\n}\n\n@media (min-width: 600px) {\n a {\n width: 18%;\n box-sizing: content-box;\n }\n}\n\na:hover {\n background-color: #000;\n}\n\n\n</code-pane>\n</code-tabs>\n<p>The <em>template</em> presents a grid of hero name links.</p>\n<ul>\n<li>The <code>*<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a></code> repeater creates as many links as are in the component's <code>heroes</code> array.</li>\n<li>The links are styled as colored blocks by the <code>dashboard.component.css</code>.</li>\n<li>The links don't go anywhere yet but <a href=\"tutorial/toh-pt5#hero-details\">they will shortly</a>.</li>\n</ul>\n<p>The <em>class</em> is similar to the <code>HeroesComponent</code> class.</p>\n<ul>\n<li>It defines a <code>heroes</code> array property.</li>\n<li>The constructor expects Angular to inject the <code>HeroService</code> into a private <code>heroService</code> property.</li>\n<li>The <code>ngOnInit()</code> lifecycle hook calls <code>getHeroes()</code>.</li>\n</ul>\n<p>This <code>getHeroes()</code> returns the sliced list of heroes at positions 1 and 5, returning only four of the Top Heroes (2nd, 3rd, 4th, and 5th).</p>\n<code-example path=\"toh-pt5/src/app/dashboard/dashboard.component.ts\" header=\"src/app/dashboard/dashboard.component.ts\" region=\"getHeroes\">\ngetHeroes(): void {\n this.heroService.getHeroes()\n .subscribe(heroes => this.heroes = heroes.slice(1, 5));\n}\n\n</code-example>\n<h3 id=\"add-the-dashboard-route\">Add the dashboard route<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#add-the-dashboard-route\"><i class=\"material-icons\">link</i></a></h3>\n<p>To navigate to the dashboard, the router needs an appropriate route.</p>\n<p>Import the <code>DashboardComponent</code> in the <code>app-routing-module.ts</code> file.</p>\n<code-example path=\"toh-pt5/src/app/app-routing.module.ts\" region=\"import-dashboard\" header=\"src/app/app-routing.module.ts (import DashboardComponent)\">\nimport { DashboardComponent } from './dashboard/dashboard.component';\n\n</code-example>\n<p>Add a route to the <code>routes</code> array that matches a path to the <code>DashboardComponent</code>.</p>\n<code-example path=\"toh-pt5/src/app/app-routing.module.ts\" header=\"src/app/app-routing.module.ts\" region=\"dashboard-route\">\n{ path: 'dashboard', component: DashboardComponent },\n\n</code-example>\n<h3 id=\"add-a-default-route\">Add a default route<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#add-a-default-route\"><i class=\"material-icons\">link</i></a></h3>\n<p>When the application starts, the browser's address bar points to the web site's root.\nThat doesn't match any existing route so the router doesn't navigate anywhere.\nThe space below the <code>&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></code> is blank.</p>\n<p>To make the application navigate to the dashboard automatically, add the following\nroute to the <code>routes</code> array.</p>\n<code-example path=\"toh-pt5/src/app/app-routing.module.ts\" header=\"src/app/app-routing.module.ts\" region=\"redirect-route\">\n{ path: '', redirectTo: '/dashboard', pathMatch: 'full' },\n\n</code-example>\n<p>This route redirects a URL that fully matches the empty path to the route whose path is <code>'/dashboard'</code>.</p>\n<p>After the browser refreshes, the router loads the <code>DashboardComponent</code>\nand the browser address bar shows the <code>/dashboard</code> URL.</p>\n<h3 id=\"add-dashboard-link-to-the-shell\">Add dashboard link to the shell<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#add-dashboard-link-to-the-shell\"><i class=\"material-icons\">link</i></a></h3>\n<p>The user should be able to navigate back and forth between the\n<code>DashboardComponent</code> and the <code>HeroesComponent</code> by clicking links in the\nnavigation area near the top of the page.</p>\n<p>Add a dashboard navigation link to the <code>AppComponent</code> shell template, just above the <em>Heroes</em> link.</p>\n<code-example path=\"toh-pt5/src/app/app.component.html\" header=\"src/app/app.component.html\">\n&#x3C;h1>{{title}}&#x3C;/h1>\n&#x3C;nav>\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/dashboard\">Dashboard&#x3C;/a>\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/heroes\">Heroes&#x3C;/a>\n&#x3C;/nav>\n&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>&#x3C;/<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n&#x3C;app-messages>&#x3C;/app-messages>\n\n</code-example>\n<p>After the browser refreshes you can navigate freely between the two views by clicking the links.</p>\n<a id=\"hero-details\"></a>\n<h2 id=\"navigating-to-hero-details\">Navigating to hero details<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#navigating-to-hero-details\"><i class=\"material-icons\">link</i></a></h2>\n<p>The <code>HeroDetailsComponent</code> displays details of a selected hero.\nAt the moment the <code>HeroDetailsComponent</code> is only visible at the bottom of the <code>HeroesComponent</code></p>\n<p>The user should be able to get to these details in three ways.</p>\n<ol>\n<li>By clicking a hero in the dashboard.</li>\n<li>By clicking a hero in the heroes list.</li>\n<li>By pasting a \"deep link\" URL into the browser address bar that identifies the hero to display.</li>\n</ol>\n<p>In this section, you'll enable navigation to the <code>HeroDetailsComponent</code>\nand liberate it from the <code>HeroesComponent</code>.</p>\n<h3 id=\"delete-hero-details-from-heroescomponent\">Delete <em>hero details</em> from <code>HeroesComponent</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#delete-hero-details-from-heroescomponent\"><i class=\"material-icons\">link</i></a></h3>\n<p>When the user clicks a hero item in the <code>HeroesComponent</code>,\nthe application should navigate to the <code>HeroDetailComponent</code>,\nreplacing the heroes list view with the hero detail view.\nThe heroes list view should no longer show hero details as it does now.</p>\n<p>Open the <code>HeroesComponent</code> template (<code>heroes/heroes.component.html</code>) and\ndelete the <code>&#x3C;app-hero-detail></code> element from the bottom.</p>\n<p>Clicking a hero item now does nothing.\nYou'll <a href=\"tutorial/toh-pt5#heroes-component-links\">fix that shortly</a> after you enable routing to the <code>HeroDetailComponent</code>.</p>\n<h3 id=\"add-a-hero-detail-route\">Add a <em>hero detail</em> route<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#add-a-hero-detail-route\"><i class=\"material-icons\">link</i></a></h3>\n<p>A URL like <code>~/detail/11</code> would be a good URL for navigating to the <em>Hero Detail</em> view of the hero whose <code>id</code> is <code>11</code>.</p>\n<p>Open <code>app-routing.module.ts</code> and import <code>HeroDetailComponent</code>.</p>\n<code-example path=\"toh-pt5/src/app/app-routing.module.ts\" region=\"import-herodetail\" header=\"src/app/app-routing.module.ts (import HeroDetailComponent)\">\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\n\n</code-example>\n<p>Then add a <em>parameterized</em> route to the <code>routes</code> array that matches the path pattern to the <em>hero detail</em> view.</p>\n<code-example path=\"toh-pt5/src/app/app-routing.module.ts\" header=\"src/app/app-routing.module.ts\" region=\"detail-route\">\n{ path: 'detail/:id', component: HeroDetailComponent },\n\n</code-example>\n<p>The colon (:) in the <code>path</code> indicates that <code>:id</code> is a placeholder for a specific hero <code>id</code>.</p>\n<p>At this point, all application routes are in place.</p>\n<code-example path=\"toh-pt5/src/app/app-routing.module.ts\" region=\"routes\" header=\"src/app/app-routing.module.ts (all routes)\">\nconst routes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: '', redirectTo: '/dashboard', pathMatch: 'full' },\n { path: 'dashboard', component: DashboardComponent },\n { path: 'detail/:id', component: HeroDetailComponent },\n { path: 'heroes', component: HeroesComponent }\n];\n\n</code-example>\n<h3 id=\"dashboardcomponent-hero-links\"><code>DashboardComponent</code> hero links<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#dashboardcomponent-hero-links\"><i class=\"material-icons\">link</i></a></h3>\n<p>The <code>DashboardComponent</code> hero links do nothing at the moment.</p>\n<p>Now that the router has a route to <code>HeroDetailComponent</code>,\nfix the dashboard hero links to navigate via the <em>parameterized</em> dashboard route.</p>\n<code-example path=\"toh-pt5/src/app/dashboard/dashboard.component.html\" region=\"click\" header=\"src/app/dashboard/dashboard.component.html (hero links)\">\n&#x3C;a *<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a>=\"let hero of heroes\"\n <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/detail/{{hero.id}}\">\n {{hero.name}}\n&#x3C;/a>\n\n</code-example>\n<p>You're using Angular <a href=\"guide/interpolation\">interpolation binding</a> within the <code>*<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a></code> repeater\nto insert the current iteration's <code>hero.id</code> into each\n<a href=\"tutorial/toh-pt5#routerlink\"><code>routerLink</code></a>.</p>\n<a id=\"heroes-component-links\"></a>\n<h3 id=\"heroescomponent-hero-links\"><code>HeroesComponent</code> hero links<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#heroescomponent-hero-links\"><i class=\"material-icons\">link</i></a></h3>\n<p>The hero items in the <code>HeroesComponent</code> are <code>&#x3C;li></code> elements whose click events\nare bound to the component's <code>onSelect()</code> method.</p>\n<code-example path=\"toh-pt4/src/app/heroes/heroes.component.html\" region=\"list\" header=\"src/app/heroes/heroes.component.html (list with onSelect)\">\n&#x3C;ul class=\"heroes\">\n &#x3C;li *<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a>=\"let hero of heroes\"\n [class.selected]=\"hero === selectedHero\"\n (click)=\"onSelect(hero)\">\n &#x3C;span class=\"badge\">{{hero.id}}&#x3C;/span> {{hero.name}}\n &#x3C;/li>\n&#x3C;/ul>\n\n</code-example>\n<p>Strip the <code>&#x3C;li></code> back to just its <code>*<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a></code>,\nwrap the badge and name in an anchor element (<code>&#x3C;a></code>),\nand add a <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a></code> attribute to the anchor that\nis the same as in the dashboard template</p>\n<code-example path=\"toh-pt5/src/app/heroes/heroes.component.html\" region=\"list\" header=\"src/app/heroes/heroes.component.html (list with links)\">\n&#x3C;ul class=\"heroes\">\n &#x3C;li *<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a>=\"let hero of heroes\">\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/detail/{{hero.id}}\">\n &#x3C;span class=\"badge\">{{hero.id}}&#x3C;/span> {{hero.name}}\n &#x3C;/a>\n &#x3C;/li>\n&#x3C;/ul>\n\n</code-example>\n<p>You'll have to fix the private stylesheet (<code>heroes.component.css</code>) to make\nthe list look as it did before.\nRevised styles are in the <a href=\"tutorial/toh-pt5#heroescomponent\">final code review</a> at the bottom of this guide.</p>\n<h4 id=\"remove-dead-code-optional\">Remove dead code (optional)<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#remove-dead-code-optional\"><i class=\"material-icons\">link</i></a></h4>\n<p>While the <code>HeroesComponent</code> class still works,\nthe <code>onSelect()</code> method and <code>selectedHero</code> property are no longer used.</p>\n<p>It's nice to tidy up and you'll be grateful to yourself later.\nHere's the class after pruning away the dead code.</p>\n<code-example path=\"toh-pt5/src/app/heroes/heroes.component.ts\" region=\"class\" header=\"src/app/heroes/heroes.component.ts (cleaned up)\">\nexport class HeroesComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n heroes: Hero[];\n\n constructor(private heroService: HeroService) { }\n\n ngOnInit() {\n this.getHeroes();\n }\n\n getHeroes(): void {\n this.heroService.getHeroes()\n .subscribe(heroes => this.heroes = heroes);\n }\n}\n\n</code-example>\n<h2 id=\"routable-herodetailcomponent\">Routable <code>HeroDetailComponent</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#routable-herodetailcomponent\"><i class=\"material-icons\">link</i></a></h2>\n<p>Previously, the parent <code>HeroesComponent</code> set the <code>HeroDetailComponent.hero</code>\nproperty and the <code>HeroDetailComponent</code> displayed the hero.</p>\n<p><code>HeroesComponent</code> doesn't do that anymore.\nNow the router creates the <code>HeroDetailComponent</code> in response to a URL such as <code>~/detail/11</code>.</p>\n<p>The <code>HeroDetailComponent</code> needs a new way to obtain the hero-to-display.\nThis section explains the following:</p>\n<ul>\n<li>Get the route that created it</li>\n<li>Extract the <code>id</code> from the route</li>\n<li>Acquire the hero with that <code>id</code> from the server via the <code>HeroService</code></li>\n</ul>\n<p>Add the following imports:</p>\n<code-example path=\"toh-pt5/src/app/hero-detail/hero-detail.component.ts\" region=\"added-imports\" header=\"src/app/hero-detail/hero-detail.component.ts\">\nimport { <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a> } from '@angular/router';\nimport { <a href=\"api/common/Location\" class=\"code-anchor\">Location</a> } from '@angular/common';\n\nimport { HeroService } from '../hero.service';\n\n</code-example>\n<a id=\"hero-detail-ctor\"></a>\n<p>Inject the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code>, <code>HeroService</code>, and <code><a href=\"api/common/Location\" class=\"code-anchor\">Location</a></code> services\ninto the constructor, saving their values in private fields:</p>\n<code-example path=\"toh-pt5/src/app/hero-detail/hero-detail.component.ts\" header=\"src/app/hero-detail/hero-detail.component.ts\" region=\"ctor\">\nconstructor(\n private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>,\n private heroService: HeroService,\n private location: <a href=\"api/common/Location\" class=\"code-anchor\">Location</a>\n) {}\n\n</code-example>\n<p>The <a href=\"api/router/ActivatedRoute\"><code>ActivatedRoute</code></a> holds information about the route to this instance of the <code>HeroDetailComponent</code>.\nThis component is interested in the route's parameters extracted from the URL.\nThe \"id\" parameter is the <code>id</code> of the hero to display.</p>\n<p>The <a href=\"tutorial/toh-pt4\"><code>HeroService</code></a> gets hero data from the remote server\nand this component will use it to get the hero-to-display.</p>\n<p>The <a href=\"api/common/Location\"><code>location</code></a> is an Angular service for interacting with the browser.\nYou'll use it <a href=\"tutorial/toh-pt5#goback\">later</a> to navigate back to the view that navigated here.</p>\n<h3 id=\"extract-the-id-route-parameter\">Extract the <code>id</code> route parameter<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#extract-the-id-route-parameter\"><i class=\"material-icons\">link</i></a></h3>\n<p>In the <code>ngOnInit()</code> <a href=\"guide/lifecycle-hooks#oninit\">lifecycle hook</a>\ncall <code>getHero()</code> and define it as follows.</p>\n<code-example path=\"toh-pt5/src/app/hero-detail/hero-detail.component.ts\" header=\"src/app/hero-detail/hero-detail.component.ts\" region=\"ngOnInit\">\nngOnInit(): void {\n this.getHero();\n}\n\ngetHero(): void {\n const id = +this.route.snapshot.paramMap.get('id');\n this.heroService.getHero(id)\n .subscribe(hero => this.hero = hero);\n}\n\n</code-example>\n<p>The <code>route.snapshot</code> is a static image of the route information shortly after the component was created.</p>\n<p>The <code>paramMap</code> is a dictionary of route parameter values extracted from the URL.\nThe <code>\"id\"</code> key returns the <code>id</code> of the hero to fetch.</p>\n<p>Route parameters are always strings.\nThe JavaScript (+) operator converts the string to a number,\nwhich is what a hero <code>id</code> should be.</p>\n<p>The browser refreshes and the application crashes with a compiler error.\n<code>HeroService</code> doesn't have a <code>getHero()</code> method.\nAdd it now.</p>\n<h3 id=\"add-heroservicegethero\">Add <code>HeroService.getHero()</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#add-heroservicegethero\"><i class=\"material-icons\">link</i></a></h3>\n<p>Open <code>HeroService</code> and add the following <code>getHero()</code> method with the <code>id</code> after the <code>getHeroes()</code> method:</p>\n<code-example path=\"toh-pt5/src/app/hero.service.ts\" region=\"getHero\" header=\"src/app/hero.service.ts (getHero)\">\ngetHero(id: number): Observable&#x3C;Hero> {\n // For now, assume that a hero with the specified `id` always exists.\n // Error handling will be added in the next step of the tutorial.\n const hero = HEROES.find(h => h.id === id) as Hero;\n this.messageService.add(`HeroService: fetched hero id=${id}`);\n return of(hero);\n}\n\n</code-example>\n<div class=\"alert is-important\">\n<p>Note the backticks ( ` ) that define a JavaScript\n<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals\"><em>template literal</em></a> for embedding the <code>id</code>.</p>\n</div>\n<p>Like <a href=\"tutorial/toh-pt4#observable-heroservice\"><code>getHeroes()</code></a>,\n<code>getHero()</code> has an asynchronous signature.\nIt returns a <em>mock hero</em> as an <code>Observable</code>, using the RxJS <code>of()</code> function.</p>\n<p>You'll be able to re-implement <code>getHero()</code> as a real <code>Http</code> request\nwithout having to change the <code>HeroDetailComponent</code> that calls it.</p>\n<h4 id=\"try-it-1\">Try it<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#try-it-1\"><i class=\"material-icons\">link</i></a></h4>\n<p>The browser refreshes and the application is working again.\nYou can click a hero in the dashboard or in the heroes list and navigate to that hero's detail view.</p>\n<p>If you paste <code>localhost:4200/detail/11</code> in the browser address bar,\nthe router navigates to the detail view for the hero with <code>id: 11</code>, \"Dr Nice\".</p>\n<a id=\"goback\"></a>\n<h3 id=\"find-the-way-back\">Find the way back<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#find-the-way-back\"><i class=\"material-icons\">link</i></a></h3>\n<p>By clicking the browser's back button,\nyou can go back to the hero list or dashboard view,\ndepending upon which sent you to the detail view.</p>\n<p>It would be nice to have a button on the <code>HeroDetail</code> view that can do that.</p>\n<p>Add a <em>go back</em> button to the bottom of the component template and bind it\nto the component's <code>goBack()</code> method.</p>\n<code-example path=\"toh-pt5/src/app/hero-detail/hero-detail.component.html\" region=\"back-button\" header=\"src/app/hero-detail/hero-detail.component.html (back button)\">\n&#x3C;button (click)=\"goBack()\">go back&#x3C;/button>\n\n</code-example>\n<p>Add a <code>goBack()</code> <em>method</em> to the component class that navigates backward one step\nin the browser's history stack\nusing the <code><a href=\"api/common/Location\" class=\"code-anchor\">Location</a></code> service that you <a href=\"tutorial/toh-pt5#hero-detail-ctor\">injected previously</a>.</p>\n<code-example path=\"toh-pt5/src/app/hero-detail/hero-detail.component.ts\" region=\"goBack\" header=\"src/app/hero-detail/hero-detail.component.ts (goBack)\">\ngoBack(): void {\n this.location.back();\n}\n\n</code-example>\n<p>Refresh the browser and start clicking.\nUsers can navigate around the app, from the dashboard to hero details and back,\nfrom heroes list to the mini detail to the hero details and back to the heroes again.</p>\n<h2 id=\"final-code-review\">Final code review<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#final-code-review\"><i class=\"material-icons\">link</i></a></h2>\n<p>Here are the code files discussed on this page.</p>\n<a id=\"approutingmodule\"></a>\n<a id=\"appmodule\"></a>\n<h4 id=\"approutingmodule-appmodule-and-heroservice\"><code>AppRoutingModule</code>, <code>AppModule</code>, and <code>HeroService</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#approutingmodule-appmodule-and-heroservice\"><i class=\"material-icons\">link</i></a></h4>\n<code-tabs>\n <code-pane header=\"src/app/app-routing.module.ts\" path=\"toh-pt5/src/app/app-routing.module.ts\">\nimport { <a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a> } from '@angular/core';\nimport { <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>, <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> } from '@angular/router';\n\nimport { DashboardComponent } from './dashboard/dashboard.component';\nimport { HeroesComponent } from './heroes/heroes.component';\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\n\nconst routes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: '', redirectTo: '/dashboard', pathMatch: 'full' },\n { path: 'dashboard', component: DashboardComponent },\n { path: 'detail/:id', component: HeroDetailComponent },\n { path: 'heroes', component: HeroesComponent }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [ RouterModule.forRoot(routes) ],\n exports: [ <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a> ]\n})\nexport class AppRoutingModule {}\n\n</code-pane>\n <code-pane header=\"src/app/app.module.ts\" path=\"toh-pt5/src/app/app.module.ts\">\nimport { <a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a> } from '@angular/core';\nimport { <a href=\"api/platform-browser/BrowserModule\" class=\"code-anchor\">BrowserModule</a> } from '@angular/platform-browser';\nimport { <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a> } from '@angular/forms';\n\nimport { AppComponent } from './app.component';\nimport { DashboardComponent } from './dashboard/dashboard.component';\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\nimport { HeroesComponent } from './heroes/heroes.component';\nimport { MessagesComponent } from './messages/messages.component';\n\nimport { AppRoutingModule } from './app-routing.module';\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n <a href=\"api/platform-browser/BrowserModule\" class=\"code-anchor\">BrowserModule</a>,\n <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>,\n AppRoutingModule\n ],\n declarations: [\n AppComponent,\n DashboardComponent,\n HeroesComponent,\n HeroDetailComponent,\n MessagesComponent\n ],\n bootstrap: [ AppComponent ]\n})\nexport class AppModule { }\n\n\n</code-pane>\n <code-pane header=\"src/app/hero.service.ts\" path=\"toh-pt5/src/app/hero.service.ts\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\n\nimport { Observable, of } from 'rxjs';\n\nimport { Hero } from './hero';\nimport { HEROES } from './mock-heroes';\nimport { MessageService } from './message.service';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({ providedIn: 'root' })\nexport class HeroService {\n\n constructor(private messageService: MessageService) { }\n\n getHeroes(): Observable&#x3C;Hero[]> {\n const heroes = of(HEROES);\n this.messageService.add('HeroService: fetched heroes');\n return heroes;\n }\n\n getHero(id: number): Observable&#x3C;Hero> {\n // For now, assume that a hero with the specified `id` always exists.\n // Error handling will be added in the next step of the tutorial.\n const hero = HEROES.find(h => h.id === id) as Hero;\n this.messageService.add(`HeroService: fetched hero id=${id}`);\n return of(hero);\n }\n}\n\n\n</code-pane>\n</code-tabs>\n<a id=\"appcomponent\"></a>\n<h4 id=\"appcomponent\"><code>AppComponent</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#appcomponent\"><i class=\"material-icons\">link</i></a></h4>\n<code-tabs>\n <code-pane header=\"src/app/app.component.html\" path=\"toh-pt5/src/app/app.component.html\">\n&#x3C;h1>{{title}}&#x3C;/h1>\n&#x3C;nav>\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/dashboard\">Dashboard&#x3C;/a>\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/heroes\">Heroes&#x3C;/a>\n&#x3C;/nav>\n&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>&#x3C;/<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n&#x3C;app-messages>&#x3C;/app-messages>\n\n</code-pane>\n\n <code-pane header=\"src/app/app.component.css\" path=\"toh-pt5/src/app/app.component.css\">\n/* AppComponent's private CSS styles */\nh1 {\n margin-bottom: 0;\n}\nnav a {\n padding: 1rem;\n text-decoration: none;\n margin-top: 10px;\n display: inline-block;\n background-color: #e8e8e8;\n color: #3d3d3d;\n border-radius: 4px;\n}\n\nnav a:hover {\n color: white;\n background-color: #42545C;\n}\nnav a.active {\n background-color: black;\n}\n\n\n</code-pane>\n</code-tabs>\n<a id=\"dashboardcomponent\"></a>\n<h4 id=\"dashboardcomponent\"><code>DashboardComponent</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#dashboardcomponent\"><i class=\"material-icons\">link</i></a></h4>\n<code-tabs>\n <code-pane header=\"src/app/dashboard/dashboard.component.html\" path=\"toh-pt5/src/app/dashboard/dashboard.component.html\">\n&#x3C;h2>Top Heroes&#x3C;/h2>\n&#x3C;div class=\"heroes-menu\">\n &#x3C;a *<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a>=\"let hero of heroes\"\n <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/detail/{{hero.id}}\">\n {{hero.name}}\n &#x3C;/a>\n&#x3C;/div>\n\n\n</code-pane>\n\n <code-pane header=\"src/app/dashboard/dashboard.component.ts\" path=\"toh-pt5/src/app/dashboard/dashboard.component.ts\">\nimport { <a href=\"api/core/Component\" class=\"code-anchor\">Component</a>, <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> } from '@angular/core';\nimport { Hero } from '../hero';\nimport { HeroService } from '../hero.service';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-dashboard',\n templateUrl: './dashboard.component.html',\n styleUrls: [ './dashboard.component.css' ]\n})\nexport class DashboardComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n heroes: Hero[] = [];\n\n constructor(private heroService: HeroService) { }\n\n ngOnInit() {\n this.getHeroes();\n }\n\n getHeroes(): void {\n this.heroService.getHeroes()\n .subscribe(heroes => this.heroes = heroes.slice(1, 5));\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"src/app/dashboard/dashboard.component.css\" path=\"toh-pt5/src/app/dashboard/dashboard.component.css\">\n/* DashboardComponent's private CSS styles */\n\nh2 {\n text-align: center;\n}\n\n.heroes-menu {\n padding: 0;\n margin: auto;\n max-width: 1000px;\n\n /* flexbox */\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: space-around;\n align-content: flex-start;\n align-items: flex-start;\n}\n\na {\n background-color: #3f525c;\n border-radius: 2px;\n padding: 1rem;\n font-size: 1.2rem;\n text-decoration: none;\n display: inline-block;\n color: #fff;\n text-align: center;\n width: 100%;\n min-width: 70px;\n margin: .5rem auto;\n box-sizing: border-box;\n\n /* flexbox */\n order: 0;\n flex: 0 1 auto;\n align-self: auto;\n}\n\n@media (min-width: 600px) {\n a {\n width: 18%;\n box-sizing: content-box;\n }\n}\n\na:hover {\n background-color: #000;\n}\n\n\n</code-pane>\n</code-tabs>\n<a id=\"heroescomponent\"></a>\n<h4 id=\"heroescomponent\"><code>HeroesComponent</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#heroescomponent\"><i class=\"material-icons\">link</i></a></h4>\n<code-tabs>\n <code-pane header=\"src/app/heroes/heroes.component.html\" path=\"toh-pt5/src/app/heroes/heroes.component.html\">\n&#x3C;h2>My Heroes&#x3C;/h2>\n&#x3C;ul class=\"heroes\">\n &#x3C;li *<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a>=\"let hero of heroes\">\n &#x3C;a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/detail/{{hero.id}}\">\n &#x3C;span class=\"badge\">{{hero.id}}&#x3C;/span> {{hero.name}}\n &#x3C;/a>\n &#x3C;/li>\n&#x3C;/ul>\n\n\n</code-pane>\n\n <code-pane header=\"src/app/heroes/heroes.component.ts\" path=\"toh-pt5/src/app/heroes/heroes.component.ts\">\nimport { <a href=\"api/core/Component\" class=\"code-anchor\">Component</a>, <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> } from '@angular/core';\n\nimport { Hero } from '../hero';\nimport { HeroService } from '../hero.service';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-heroes',\n templateUrl: './heroes.component.html',\n styleUrls: ['./heroes.component.css']\n})\nexport class HeroesComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n heroes: Hero[];\n\n constructor(private heroService: HeroService) { }\n\n ngOnInit() {\n this.getHeroes();\n }\n\n getHeroes(): void {\n this.heroService.getHeroes()\n .subscribe(heroes => this.heroes = heroes);\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"src/app/heroes/heroes.component.css\" path=\"toh-pt5/src/app/heroes/heroes.component.css\">\n/* HeroesComponent's private CSS styles */\n.heroes {\n margin: 0 0 2em 0;\n list-style-type: none;\n padding: 0;\n width: 15em;\n}\n.heroes li {\n position: relative;\n cursor: pointer;\n}\n\n.heroes li:hover {\n left: .1em;\n}\n\n.heroes a {\n color: #333;\n text-decoration: none;\n background-color: #EEE;\n margin: .5em;\n padding: .3em 0;\n height: 1.6em;\n border-radius: 4px;\n display: block;\n width: 100%;\n}\n\n.heroes a:hover {\n color: #2c3a41;\n background-color: #e6e6e6;\n}\n\n.heroes a:active {\n background-color: #525252;\n color: #fafafa;\n}\n\n.heroes .badge {\n display: inline-block;\n font-size: small;\n color: white;\n padding: 0.8em 0.7em 0 0.7em;\n background-color:#405061;\n line-height: 1em;\n position: relative;\n left: -1px;\n top: -4px;\n height: 1.8em;\n min-width: 16px;\n text-align: right;\n margin-right: .8em;\n border-radius: 4px 0 0 4px;\n}\n\n\n</code-pane>\n</code-tabs>\n<a id=\"herodetailcomponent\"></a>\n<h4 id=\"herodetailcomponent\"><code>HeroDetailComponent</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#herodetailcomponent\"><i class=\"material-icons\">link</i></a></h4>\n<code-tabs>\n <code-pane header=\"src/app/hero-detail/hero-detail.component.html\" path=\"toh-pt5/src/app/hero-detail/hero-detail.component.html\">\n&#x3C;div *<a href=\"api/common/NgIf\" class=\"code-anchor\">ngIf</a>=\"hero\">\n &#x3C;h2>{{hero.name | <a href=\"api/common/UpperCasePipe\" class=\"code-anchor\">uppercase</a>}} Details&#x3C;/h2>\n &#x3C;div>&#x3C;span>id: &#x3C;/span>{{hero.id}}&#x3C;/div>\n &#x3C;div>\n &#x3C;label for=\"hero-name\">Hero name: &#x3C;/label>\n &#x3C;input id=\"hero-name\" [(<a href=\"api/forms/NgModel\" class=\"code-anchor\">ngModel</a>)]=\"hero.name\" placeholder=\"Hero name\"/>\n &#x3C;/div>\n &#x3C;button (click)=\"goBack()\">go back&#x3C;/button>\n&#x3C;/div>\n\n\n</code-pane>\n\n <code-pane header=\"src/app/hero-detail/hero-detail.component.ts\" path=\"toh-pt5/src/app/hero-detail/hero-detail.component.ts\">\nimport { <a href=\"api/core/Component\" class=\"code-anchor\">Component</a>, <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> } from '@angular/core';\nimport { <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a> } from '@angular/router';\nimport { <a href=\"api/common/Location\" class=\"code-anchor\">Location</a> } from '@angular/common';\n\nimport { Hero } from '../hero';\nimport { HeroService } from '../hero.service';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-hero-detail',\n templateUrl: './hero-detail.component.html',\n styleUrls: [ './hero-detail.component.css' ]\n})\nexport class HeroDetailComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n hero: Hero;\n\n constructor(\n private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>,\n private heroService: HeroService,\n private location: <a href=\"api/common/Location\" class=\"code-anchor\">Location</a>\n ) {}\n\n ngOnInit(): void {\n this.getHero();\n }\n\n getHero(): void {\n const id = +this.route.snapshot.paramMap.get('id');\n this.heroService.getHero(id)\n .subscribe(hero => this.hero = hero);\n }\n\n goBack(): void {\n this.location.back();\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"src/app/hero-detail/hero-detail.component.css\" path=\"toh-pt5/src/app/hero-detail/hero-detail.component.css\">\n/* HeroDetailComponent's private CSS styles */\nlabel {\n color: #435960;\n font-weight: bold;\n}\ninput {\n font-size: 1em;\n padding: .5rem;\n}\nbutton {\n margin-top: 20px;\n background-color: #eee;\n padding: 1rem;\n border-radius: 4px;\n font-size: 1rem;\n}\nbutton:hover {\n background-color: #cfd8dc;\n}\nbutton:disabled {\n background-color: #eee;\n color: #ccc;\n cursor: auto;\n}\n\n\n</code-pane>\n</code-tabs>\n<h2 id=\"summary\">Summary<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"tutorial/toh-pt5#summary\"><i class=\"material-icons\">link</i></a></h2>\n<ul>\n<li>You added the Angular router to navigate among different components.</li>\n<li>You turned the <code>AppComponent</code> into a navigation shell with <code>&#x3C;a></code> links and a <code>&#x3C;<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></code>.</li>\n<li>You configured the router in an <code>AppRoutingModule</code></li>\n<li>You defined routes, a redirect route, and a parameterized route.</li>\n<li>You used the <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a></code> directive in anchor elements.</li>\n<li>You refactored a tightly-coupled master/detail view into a routed detail view.</li>\n<li>You used router link parameters to navigate to the detail view of a user-selected hero.</li>\n<li>You shared the <code>HeroService</code> among multiple components.</li>\n</ul>\n\n \n</div>\n\n<!-- links to this doc:\n - guide/example-apps-list\n - tutorial/toh-pt4\n-->\n<!-- links from this doc:\n - /api/router/RouterLink\n - api/common/CommonModule\n - api/common/Location\n - api/common/NgForOf\n - api/common/NgIf\n - api/common/UpperCasePipe\n - api/core/Component\n - api/core/Injectable\n - api/core/NgModule\n - api/core/OnInit\n - api/forms/FormsModule\n - api/forms/NgModel\n - api/platform-browser/BrowserModule\n - api/router/ActivatedRoute\n - api/router/Route\n - api/router/RouterLink\n - api/router/RouterModule\n - api/router/RouterModule#forRoot\n - api/router/RouterOutlet\n - api/router/Routes\n - guide/interpolation\n - guide/lifecycle-hooks#oninit\n - tutorial/toh-pt4\n - tutorial/toh-pt4#observable-heroservice\n - tutorial/toh-pt5#add-a-dashboard-view\n - tutorial/toh-pt5#add-a-default-route\n - tutorial/toh-pt5#add-a-hero-detail-route\n - tutorial/toh-pt5#add-a-navigation-link-routerlink\n - tutorial/toh-pt5#add-dashboard-link-to-the-shell\n - tutorial/toh-pt5#add-heroservicegethero\n - tutorial/toh-pt5#add-navigation-with-routing\n - tutorial/toh-pt5#add-routeroutlet\n - tutorial/toh-pt5#add-the-approutingmodule\n - tutorial/toh-pt5#add-the-dashboard-route\n - tutorial/toh-pt5#appcomponent\n - tutorial/toh-pt5#approutingmodule-appmodule-and-heroservice\n - tutorial/toh-pt5#dashboardcomponent\n - tutorial/toh-pt5#dashboardcomponent-hero-links\n - tutorial/toh-pt5#delete-hero-details-from-heroescomponent\n - tutorial/toh-pt5#extract-the-id-route-parameter\n - tutorial/toh-pt5#final-code-review\n - tutorial/toh-pt5#find-the-way-back\n - tutorial/toh-pt5#goback\n - tutorial/toh-pt5#hero-detail-ctor\n - tutorial/toh-pt5#hero-details\n - tutorial/toh-pt5#herodetailcomponent\n - tutorial/toh-pt5#heroes-component-links\n - tutorial/toh-pt5#heroescomponent\n - tutorial/toh-pt5#heroescomponent-hero-links\n - tutorial/toh-pt5#navigating-to-hero-details\n - tutorial/toh-pt5#remove-dead-code-optional\n - tutorial/toh-pt5#routable-herodetailcomponent\n - tutorial/toh-pt5#routerlink\n - tutorial/toh-pt5#routermoduleforroot\n - tutorial/toh-pt5#routes\n - tutorial/toh-pt5#summary\n - tutorial/toh-pt5#try-it\n - tutorial/toh-pt5#try-it-1\n - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Template_literals\n - https://github.com/angular/angular/edit/master/aio/content/tutorial/toh-pt5.md?message=docs%3A%20describe%20your%20change...\n-->"
}