5 lines
264 KiB
JSON
5 lines
264 KiB
JSON
{
|
|
"id": "guide/router-tutorial-toh",
|
|
"title": "Router tutorial: tour of heroes",
|
|
"contents": "\n\n\n<div class=\"github-links\">\n <a href=\"https://github.com/angular/angular/edit/master/aio/content/guide/router-tutorial-toh.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 <a id=\"router-tutorial\"></a>\n<h1 id=\"router-tutorial-tour-of-heroes\">Router tutorial: tour of heroes<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#router-tutorial-tour-of-heroes\"><i class=\"material-icons\">link</i></a></h1>\n<p>This tutorial provides an extensive overview of the Angular router.\nIn this tutorial, you will build upon a basic router configuration to explore features such as child routes, route parameters, lazy load NgModules, guard routes, and preloading data to improve the user experience.</p>\n<p>For a working example of the final version of the app, see the <live-example name=\"router\"></live-example>.</p>\n<a id=\"router-tutorial-objectives\"></a>\n<h2 id=\"objectives\">Objectives<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#objectives\"><i class=\"material-icons\">link</i></a></h2>\n<p>This guide describes development of a multi-page routed sample application.\nAlong the way, it highlights key features of the router such as:</p>\n<ul>\n<li>Organizing the application features into modules.</li>\n<li>Navigating to a component (<em>Heroes</em> link to \"Heroes List\").</li>\n<li>Including a route parameter (passing the Hero <code>id</code> while routing to the \"Hero Detail\").</li>\n<li>Child routes (the <em>Crisis Center</em> has its own routes).</li>\n<li>The <code><a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a></code> guard (checking route access).</li>\n<li>The <code><a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a></code> guard (checking child route access).</li>\n<li>The <code><a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a></code> guard (ask permission to discard unsaved changes).</li>\n<li>The <code><a href=\"api/router/Resolve\" class=\"code-anchor\">Resolve</a></code> guard (pre-fetching route data).</li>\n<li>Lazy loading an <code><a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a></code>.</li>\n<li>The <code><a href=\"api/router/CanLoad\" class=\"code-anchor\">CanLoad</a></code> guard (check before loading feature module assets).</li>\n</ul>\n<p>This guide proceeds as a sequence of milestones as if you were building the app step-by-step, but assumes you are familiar with basic <a href=\"guide/architecture\">Angular concepts</a>.\nFor a general introduction to angular, see the <a href=\"start\">Getting Started</a>. For a more in-depth overview, see the <a href=\"tutorial\">Tour of Heroes</a> tutorial.</p>\n<h2 id=\"prerequisites\">Prerequisites<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#prerequisites\"><i class=\"material-icons\">link</i></a></h2>\n<p>To complete this tutorial, you should have a basic understanding of the following concepts:</p>\n<ul>\n<li>JavaScript</li>\n<li>HTML</li>\n<li>CSS</li>\n<li><a href=\"/cli\">Angular CLI</a></li>\n</ul>\n<p>You might find the <a href=\"/tutorial\">Tour of Heroes tutorial</a> helpful, but it is not required.</p>\n<h2 id=\"the-sample-application-in-action\">The sample application in action<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#the-sample-application-in-action\"><i class=\"material-icons\">link</i></a></h2>\n<p>The sample application for this tutorial helps the Hero Employment Agency find crises for heroes to solve.</p>\n<p>The application has three main feature areas:</p>\n<ol>\n<li>A <em>Crisis Center</em> for maintaining the list of crises for assignment to heroes.</li>\n<li>A <em>Heroes</em> area for maintaining the list of heroes employed by the agency.</li>\n<li>An <em>Admin</em> area to manage the list of crises and heroes.</li>\n</ol>\n<p>Try it by clicking on this <live-example name=\"router\" title=\"Hero Employment Agency Live Example\">live example link</live-example>.</p>\n<p>The app renders with a row of navigation buttons and the <em>Heroes</em> view with its list of heroes.</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/router/hero-list.png\" alt=\"Hero List\" width=\"250\" height=\"225\">\n</div>\n<p>Select one hero and the app takes you to a hero editing screen.</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/router/hero-detail.png\" alt=\"Crisis Center Detail\" width=\"250\" height=\"162\">\n</div>\n<p>Alter the name.\nClick the \"Back\" button and the app returns to the heroes list which displays the changed hero name.\nNotice that the name change took effect immediately.</p>\n<p>Had you clicked the browser's back button instead of the app's \"Back\" button, the app would have returned you to the heroes list as well.\nAngular app navigation updates the browser history as normal web navigation does.</p>\n<p>Now click the <em>Crisis Center</em> link for a list of ongoing crises.</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/router/crisis-center-list.png\" alt=\"Crisis Center List\" width=\"250\" height=\"209\">\n</div>\n<p>Select a crisis and the application takes you to a crisis editing screen.\nThe <em>Crisis Detail</em> appears in a child component on the same page, beneath the list.</p>\n<p>Alter the name of a crisis.\nNotice that the corresponding name in the crisis list does <em>not</em> change.</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/router/crisis-center-detail.png\" alt=\"Crisis Center Detail\" width=\"250\" height=\"281\">\n</div>\n<p>Unlike <em>Hero Detail</em>, which updates as you type, <em>Crisis Detail</em> changes are temporary until you either save or discard them by pressing the \"Save\" or \"Cancel\" buttons.\nBoth buttons navigate back to the <em>Crisis Center</em> and its list of crises.</p>\n<p>Click the browser back button or the \"Heroes\" link to activate a dialog.</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/router/confirm-dialog.png\" alt=\"Confirm Dialog\" width=\"250\" height=\"101\">\n</div>\n<p>You can say \"OK\" and lose your changes or click \"Cancel\" and continue editing.</p>\n<p>Behind this behavior is the router's <code><a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a></code> guard.\nThe guard gives you a chance to clean-up or ask the user's permission before navigating away from the current view.</p>\n<p>The <code>Admin</code> and <code>Login</code> buttons illustrate other router capabilities covered later in the guide.</p>\n<a id=\"getting-started\"></a>\n<h2 id=\"milestone-1-getting-started\">Milestone 1: Getting started<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#milestone-1-getting-started\"><i class=\"material-icons\">link</i></a></h2>\n<p>Begin with a basic version of the app that navigates between two empty views.</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/router/router-1-anim.gif\" alt=\"App in action\" width=\"250\" height=\"152\">\n</div>\n<a id=\"import\"></a>\n<p>Generate a sample application with the Angular CLI.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng new angular-router-sample\n</code-example>\n<h3 id=\"define-routes\">Define Routes<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#define-routes\"><i class=\"material-icons\">link</i></a></h3>\n<p>A router must be configured with a list of route definitions.</p>\n<p>Each definition translates to a <a href=\"api/router/Route\">Route</a> object which has two things: a <code>path</code>, the URL path segment for this route; and a <code>component</code>, the component associated with this route.</p>\n<p>The router draws upon its registry of definitions when the browser URL changes or when application code tells the router to navigate along a route path.</p>\n<p>The first route does the following:</p>\n<ul>\n<li>\n<p>When the browser's location URL changes to match the path segment <code>/crisis-center</code>, then the router activates an instance of the <code>CrisisListComponent</code> and displays its view.</p>\n</li>\n<li>\n<p>When the application requests navigation to the path <code>/crisis-center</code>, the router activates an instance of <code>CrisisListComponent</code>, displays its view, and updates the browser's address location and history with the URL for that path.</p>\n</li>\n</ul>\n<p>The first configuration defines an array of two routes with minimal paths leading to the <code>CrisisListComponent</code> and <code>HeroListComponent</code>.</p>\n<p>Generate the <code>CrisisList</code> and <code>HeroList</code> components so that the router has something to render.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate component crisis-list\n</code-example>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate component hero-list\n</code-example>\n<p>Replace the contents of each component with the sample HTML below.</p>\n<code-tabs>\n\n <code-pane header=\"src/app/crisis-list/crisis-list.component.html\" path=\"router/src/app/crisis-list/crisis-list.component.1.html\">\n<h2>CRISIS CENTER</h2>\n<p>Get your crisis here</p>\n\n\n</code-pane>\n\n <code-pane header=\"src/app/hero-list/hero-list.component.html\" path=\"router/src/app/hero-list/hero-list.component.1.html\" region=\"template\">\n<h2>HEROES</h2>\n<p>Get your heroes here</p>\n\n\n</code-pane>\n\n</code-tabs>\n<h3 id=\"register-router-and-routes\">Register <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> and <code><a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a></code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#register-router-and-routes\"><i class=\"material-icons\">link</i></a></h3>\n<p>In order to use the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code>, you must first register the <code><a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a></code> from the <code>@angular/router</code> package.\nDefine an array of routes, <code>appRoutes</code>, and pass them to the <code><a href=\"api/router/RouterModule#forRoot\" class=\"code-anchor\">RouterModule.forRoot()</a></code> method.\nThe <code><a href=\"api/router/RouterModule#forRoot\" class=\"code-anchor\">RouterModule.forRoot()</a></code> method returns a module that contains the configured <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> service provider, plus other providers that the routing library requires.\nOnce the application is bootstrapped, the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> performs the initial navigation based on the current browser URL.</p>\n<div class=\"alert is-important\">\n<p> <strong>Note:</strong> The <code><a href=\"api/router/RouterModule#forRoot\" class=\"code-anchor\">RouterModule.forRoot()</a></code> method is a pattern used to register application-wide providers. Read more about application-wide providers in the <a href=\"guide/singleton-services#forRoot-router\">Singleton services</a> guide.</p>\n</div>\n<code-example path=\"router/src/app/app.module.1.ts\" header=\"src/app/app.module.ts (first-config)\" region=\"first-config\">\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';\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 { AppComponent } from './app.component';\nimport { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { HeroListComponent } from './hero-list/hero-list.component';\n\nconst appRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'crisis-center', component: CrisisListComponent },\n { path: 'heroes', component: HeroListComponent },\n];\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 RouterModule.forRoot(\n appRoutes,\n { enableTracing: true } // <-- debugging purposes only\n )\n ],\n declarations: [\n AppComponent,\n HeroListComponent,\n CrisisListComponent,\n ],\n bootstrap: [ AppComponent ]\n})\nexport class AppModule { }\n\n</code-example>\n<div class=\"alert is-helpful\">\n<p>Adding the configured <code><a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a></code> to the <code>AppModule</code> is sufficient for minimal route configurations.\nHowever, as the application grows, <a href=\"guide/router-tutorial-toh#refactor-the-routing-configuration-into-a-routing-module\">refactor the routing configuration</a> into a separate file and create a <a href=\"guide/router-tutorial-toh#routing-module\">Routing Module</a>.\nA routing module is a special type of <code>Service Module</code> dedicated to routing.</p>\n</div>\n<p>Registering the <code><a href=\"api/router/RouterModule#forRoot\" class=\"code-anchor\">RouterModule.forRoot()</a></code> in the <code>AppModule</code> <code>imports</code> array makes the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> service available everywhere in the application.</p>\n<a id=\"shell\"></a>\n<h3 id=\"add-the-router-outlet\">Add the Router Outlet<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#add-the-router-outlet\"><i class=\"material-icons\">link</i></a></h3>\n<p>The root <code>AppComponent</code> is the application shell. It has a title, a navigation bar with two links, and a router outlet where the router renders components.</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/router/shell-and-outlet.png\" alt=\"Shell\" width=\"300\" height=\"102\">\n</div>\n<p>The router outlet serves as a placeholder where the routed components are rendered.</p>\n<a id=\"shell-template\"></a>\n<p>The corresponding component template looks like this:</p>\n<code-example path=\"router/src/app/app.component.1.html\" header=\"src/app/app.component.html\">\n<h1>Angular <a href=\"api/router/Router\" class=\"code-anchor\">Router</a></h1>\n<nav>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/crisis-center\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Crisis Center</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/heroes\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Heroes</a>\n</nav>\n<<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n\n</code-example>\n<a id=\"wildcard\"></a>\n<h3 id=\"define-a-wildcard-route\">Define a Wildcard route<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#define-a-wildcard-route\"><i class=\"material-icons\">link</i></a></h3>\n<p>You've created two routes in the app so far, one to <code>/crisis-center</code> and the other to <code>/heroes</code>.\nAny other URL causes the router to throw an error and crash the app.</p>\n<p>Add a wildcard route to intercept invalid URLs and handle them gracefully.\nA wildcard route has a path consisting of two asterisks.\nIt matches every URL.\nThus, the router selects this wildcard route if it can't match a route earlier in the configuration.\nA wildcard route can navigate to a custom \"404 Not Found\" component or <a href=\"guide/router-tutorial-toh#redirect\">redirect</a> to an existing route.</p>\n<div class=\"alert is-helpful\">\n<p>The router selects the route with a <a href=\"/guide/router#example-config\"><em>first match wins</em></a> strategy.\nBecause a wildcard route is the least specific route, place it last in the route configuration.</p>\n</div>\n<p>To test this feature, add a button with a <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> to the <code>HeroListComponent</code> template and set the link to a non-existant route called <code>\"/sidekicks\"</code>.</p>\n<code-example path=\"router/src/app/hero-list/hero-list.component.1.html\" header=\"src/app/hero-list/hero-list.component.html (excerpt)\">\n<h2>HEROES</h2>\n<p>Get your heroes here</p>\n\n<button <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/sidekicks\">Go to sidekicks</button>\n\n\n</code-example>\n<p>The application fails if the user clicks that button because you haven't defined a <code>\"/sidekicks\"</code> route yet.</p>\n<p>Instead of adding the <code>\"/sidekicks\"</code> route, define a <code>wildcard</code> route and have it navigate to a <code>PageNotFoundComponent</code>.</p>\n<code-example path=\"router/src/app/app.module.1.ts\" header=\"src/app/app.module.ts (wildcard)\" region=\"wildcard\">\n{ path: '**', component: PageNotFoundComponent }\n\n</code-example>\n<p>Create the <code>PageNotFoundComponent</code> to display when users visit invalid URLs.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate component page-not-found\n</code-example>\n<code-example path=\"router/src/app/page-not-found/page-not-found.component.html\" header=\"src/app/page-not-found.component.html (404 component)\">\n<h2>Page not found</h2>\n\n</code-example>\n<p>Now when the user visits <code>/sidekicks</code>, or any other invalid URL, the browser displays \"Page not found\".\nThe browser address bar continues to point to the invalid URL.</p>\n<a id=\"redirect\"></a>\n<h3 id=\"set-up-redirects\">Set up redirects<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#set-up-redirects\"><i class=\"material-icons\">link</i></a></h3>\n<p>When the application launches, the initial URL in the browser bar is by default:</p>\n<code-example>\n localhost:4200\n</code-example>\n<p>That doesn't match any of the hard-coded routes which means the router falls through to the wildcard route and displays the <code>PageNotFoundComponent</code>.</p>\n<p>The application needs a default route to a valid page.\nThe default page for this app is the list of heroes.\nThe app should navigate there as if the user clicked the \"Heroes\" link or pasted <code>localhost:4200/heroes</code> into the address bar.</p>\n<p>Add a <code>redirect</code> route that translates the initial relative URL (<code>''</code>) to the desired default path (<code>/heroes</code>).</p>\n<p>Add the default route somewhere <em>above</em> the wildcard route.\nIt's just above the wildcard route in the following excerpt showing the complete <code>appRoutes</code> for this milestone.</p>\n<code-example path=\"router/src/app/app-routing.module.1.ts\" header=\"src/app/app-routing.module.ts (appRoutes)\" region=\"appRoutes\">\nconst appRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'crisis-center', component: CrisisListComponent },\n { path: 'heroes', component: HeroListComponent },\n { path: '', redirectTo: '/heroes', pathMatch: 'full' },\n { path: '**', component: PageNotFoundComponent }\n];\n\n</code-example>\n<p>The browser address bar shows <code>.../heroes</code> as if you'd navigated there directly.</p>\n<p>A redirect route requires a <code>pathMatch</code> property to tell the router how to match a URL to the path of a route.\nIn this app, the router should select the route to the <code>HeroListComponent</code> only when the <em>entire URL</em> matches <code>''</code>, so set the <code>pathMatch</code> value to <code>'full'</code>.</p>\n<a id=\"pathmatch\"></a>\n<div class=\"callout is-helpful\">\n <header>Spotlight on pathMatch</header>\n<p> Technically, <code>pathMatch = 'full'</code> results in a route hit when the <em>remaining</em>, unmatched segments of the URL match <code>''</code>.\nIn this example, the redirect is in a top level route so the <em>remaining</em> URL and the <em>entire</em> URL are the same thing.</p>\n<p> The other possible <code>pathMatch</code> value is <code>'prefix'</code> which tells the router to match the redirect route when the remaining URL begins with the redirect route's prefix path.\nThis doesn't apply to this sample app because if the <code>pathMatch</code> value were <code>'prefix'</code>, every URL would match <code>''</code>.</p>\n<p> Try setting it to <code>'prefix'</code> and clicking the <code>Go to sidekicks</code> button.\nSince that's a bad URL, you should see the \"Page not found\" page.\nInstead, you're still on the \"Heroes\" page.\nEnter a bad URL in the browser address bar.\nYou're instantly re-routed to <code>/heroes</code>.\nEvery URL, good or bad, that falls through to this route definition is a match.</p>\n<p> The default route should redirect to the <code>HeroListComponent</code> only when the entire url is <code>''</code>.\nRemember to restore the redirect to <code>pathMatch = 'full'</code>.</p>\n<p> Learn more in Victor Savkin's\n<a href=\"https://vsavkin.tumblr.com/post/146722301646/angular-router-empty-paths-componentless-routes\">post on redirects</a>.</p>\n</div>\n<h3 id=\"milestone-1-wrap-up\">Milestone 1 wrap up<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#milestone-1-wrap-up\"><i class=\"material-icons\">link</i></a></h3>\n<p>Your sample app can switch between two views when the user clicks a link.</p>\n<p>Milestone 1 has covered how to do the following:</p>\n<ul>\n<li>Load the router library.</li>\n<li>Add a nav bar to the shell template with anchor tags, <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a></code> and <code><a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a></code> directives.</li>\n<li>Add a <code><a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a></code> to the shell template where views are displayed.</li>\n<li>Configure the router module with <code><a href=\"api/router/RouterModule#forRoot\" class=\"code-anchor\">RouterModule.forRoot()</a></code>.</li>\n<li>Set the router to compose HTML5 browser URLs.</li>\n<li>Handle invalid routes with a <code>wildcard</code> route.</li>\n<li>Navigate to the default route when the app launches with an empty path.</li>\n</ul>\n<p>The starter app's structure looks like this:</p>\n<div class=\"filetree\">\n <div class=\"file\">\n angular-router-sample\n </div>\n <div class=\"children\">\n <div class=\"file\">\n src\n </div>\n <div class=\"children\">\n <div class=\"file\">\n app\n </div>\n <div class=\"children\">\n <div class=\"file\">\n crisis-list\n </div>\n <div class=\"children\">\n <div class=\"file\">\n<p> crisis-list.component.css</p>\n </div>\n <div class=\"file\">\n<p> crisis-list.component.html</p>\n </div>\n <div class=\"file\">\n<p> crisis-list.component.ts</p>\n </div>\n </div>\n <div class=\"file\">\n hero-list\n </div>\n <div class=\"children\">\n <div class=\"file\">\n<p> hero-list.component.css</p>\n </div>\n <div class=\"file\">\n<p> hero-list.component.html</p>\n </div>\n <div class=\"file\">\n<p> hero-list.component.ts</p>\n </div>\n </div>\n <div class=\"file\">\n page-not-found\n </div>\n <div class=\"children\">\n <div class=\"file\">\n<p> page-not-found.component.css</p>\n </div>\n <div class=\"file\">\n<p> page-not-found.component.html</p>\n </div>\n <div class=\"file\">\n<p> page-not-found.component.ts</p>\n </div>\n </div>\n <div class=\"file\">\n app.component.css\n </div>\n <div class=\"file\">\n app.component.html\n </div>\n <div class=\"file\">\n app.component.ts\n </div>\n <div class=\"file\">\n app.module.ts\n </div>\n </div>\n <div class=\"file\">\n main.ts\n </div>\n <div class=\"file\">\n index.html\n </div>\n <div class=\"file\">\n styles.css\n </div>\n <div class=\"file\">\n tsconfig.json\n </div>\n </div>\n <div class=\"file\">\n node_modules ...\n </div>\n <div class=\"file\">\n package.json\n </div>\n </div>\n</div>\n<p>Here are the files in this milestone.</p>\n<code-tabs>\n\n <code-pane header=\"app.component.html\" path=\"router/src/app/app.component.1.html\">\n<h1>Angular <a href=\"api/router/Router\" class=\"code-anchor\">Router</a></h1>\n<nav>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/crisis-center\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Crisis Center</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/heroes\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Heroes</a>\n</nav>\n<<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n\n</code-pane>\n\n <code-pane header=\"app.module.ts\" path=\"router/src/app/app.module.1.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';\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 { AppComponent } from './app.component';\nimport { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { HeroListComponent } from './hero-list/hero-list.component';\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\n\nconst appRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'crisis-center', component: CrisisListComponent },\n { path: 'heroes', component: HeroListComponent },\n\n { path: '', redirectTo: '/heroes', pathMatch: 'full' },\n { path: '**', component: PageNotFoundComponent }\n];\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 RouterModule.forRoot(\n appRoutes,\n { enableTracing: true } // <-- debugging purposes only\n )\n ],\n declarations: [\n AppComponent,\n HeroListComponent,\n CrisisListComponent,\n PageNotFoundComponent\n ],\n bootstrap: [ AppComponent ]\n})\nexport class AppModule { }\n\n\n</code-pane>\n\n <code-pane header=\"hero-list/hero-list.component.html\" path=\"router/src/app/hero-list/hero-list.component.1.html\">\n<h2>HEROES</h2>\n<p>Get your heroes here</p>\n\n<button <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/sidekicks\">Go to sidekicks</button>\n\n\n</code-pane>\n\n <code-pane header=\"crisis-list/crisis-list.component.html\" path=\"router/src/app/crisis-list/crisis-list.component.1.html\">\n<h2>CRISIS CENTER</h2>\n<p>Get your crisis here</p>\n\n\n</code-pane>\n\n <code-pane header=\"page-not-found/page-not-found.component.html\" path=\"router/src/app/page-not-found/page-not-found.component.html\">\n<h2>Page not found</h2>\n\n</code-pane>\n\n <code-pane header=\"index.html\" path=\"router/src/index.html\">\n<html lang=\"en\">\n <head>\n <!-- Set the base href -->\n <base href=\"/\">\n <title>Angular <a href=\"api/router/Router\" class=\"code-anchor\">Router</a></title>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n </head>\n\n <body>\n <app-root></app-root>\n </body>\n\n</html>\n\n</code-pane>\n\n</code-tabs>\n<a id=\"routing-module\"></a>\n<h2 id=\"milestone-2-routing-module\">Milestone 2: <em>Routing module</em><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#milestone-2-routing-module\"><i class=\"material-icons\">link</i></a></h2>\n<p>This milestone shows you how to configure a special-purpose module called a <em>Routing Module</em>, which holds your app's routing configuration.</p>\n<p>The Routing Module has several characteristics:</p>\n<ul>\n<li>Separates routing concerns from other application concerns.</li>\n<li>Provides a module to replace or remove when testing the application.</li>\n<li>Provides a well-known location for routing service providers such as guards and resolvers.</li>\n<li>Does not declare components.</li>\n</ul>\n<a id=\"integrate-routing\"></a>\n<h3 id=\"integrate-routing-with-your-app\">Integrate routing with your app<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#integrate-routing-with-your-app\"><i class=\"material-icons\">link</i></a></h3>\n<p>The sample routing application does not include routing by default.\nWhen you use the <a href=\"cli\">Angular CLI</a> to create a project that does use routing, set the <code>--routing</code> option for the project or app, and for each NgModule.\nWhen you create or initialize a new project (using the CLI <a href=\"cli/new\"><code>ng new</code></a> command) or a new app (using the <a href=\"cli/generate\"><code>ng generate app</code></a> command), specify the <code>--routing</code> option.\nThis tells the CLI to include the <code>@angular/router</code> npm package and create a file named <code>app-routing.module.ts</code>.\nYou can then use routing in any NgModule that you add to the project or app.</p>\n<p>For example, the following command generates an NgModule that can use routing.</p>\n<code-example language=\"sh\">\nng generate module my-module --routing\n</code-example>\n<p>This creates a separate file named <code>my-module-routing.module.ts</code> to store the NgModule's routes.\nThe file includes an empty <code><a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a></code> object that you can fill with routes to different components and NgModules.</p>\n<a id=\"routing-refactor\"></a>\n<h3 id=\"refactor-the-routing-configuration-into-a-routing-module\">Refactor the routing configuration into a routing module<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#refactor-the-routing-configuration-into-a-routing-module\"><i class=\"material-icons\">link</i></a></h3>\n<p>Create an <code>AppRouting</code> module in the <code>/app</code> folder to contain the routing configuration.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate module app-routing --module app --flat\n</code-example>\n<p>Import the <code>CrisisListComponent</code>, <code>HeroListComponent</code>, and <code>PageNotFoundComponent</code> symbols\njust like you did in the <code>app.module.ts</code>.\nThen move the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> imports and routing configuration, including <code><a href=\"api/router/RouterModule#forRoot\" class=\"code-anchor\">RouterModule.forRoot()</a></code>, into this routing module.</p>\n<p>Re-export the Angular <code><a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a></code> by adding it to the module <code>exports</code> array.\nBy re-exporting the <code><a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a></code> here, the components declared in <code>AppModule</code> have access to router directives such as <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> and <code><a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a></code>.</p>\n<p>After these steps, the file should look like this.</p>\n<code-example path=\"router/src/app/app-routing.module.1.ts\" header=\"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 { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { HeroListComponent } from './hero-list/hero-list.component';\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\n\nconst appRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'crisis-center', component: CrisisListComponent },\n { path: 'heroes', component: HeroListComponent },\n { path: '', redirectTo: '/heroes', pathMatch: 'full' },\n { path: '**', component: PageNotFoundComponent }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forRoot(\n appRoutes,\n { enableTracing: true } // <-- debugging purposes only\n )\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class AppRoutingModule {}\n\n\n</code-example>\n<p>Next, update the <code>app.module.ts</code> file by removing <code>RouterModule.forRoot</code> in the <code>imports</code> array.</p>\n<code-example path=\"router/src/app/app.module.2.ts\" header=\"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 { AppRoutingModule } from './app-routing.module';\n\nimport { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { HeroListComponent } from './hero-list/hero-list.component';\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\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 HeroListComponent,\n CrisisListComponent,\n PageNotFoundComponent\n ],\n bootstrap: [ AppComponent ]\n})\nexport class AppModule { }\n\n\n</code-example>\n<div class=\"alert is-helpful\">\n<p>Later, this guide shows you how to create <a href=\"guide/router-tutorial-toh#heroes-functionality\">multiple routing modules</a> and import those routing modules <a href=\"guide/router-tutorial-toh#routing-module-order\">in the correct order</a>.</p>\n</div>\n<p>The application continues to work just the same, and you can use <code>AppRoutingModule</code> as the central place to maintain future routing configuration.</p>\n<a id=\"why-routing-module\"></a>\n<h3 id=\"benefits-of-a-routing-module\">Benefits of a routing module<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#benefits-of-a-routing-module\"><i class=\"material-icons\">link</i></a></h3>\n<p>The routing module, often called the <code>AppRoutingModule</code>, replaces the routing configuration in the root or feature module.</p>\n<p>The routing module is helpful as your app grows and when the configuration includes specialized guard and resolver services.</p>\n<p>Some developers skip the routing module when the configuration is minimal and merge the routing configuration directly into the companion module (for example, <code>AppModule</code>).</p>\n<p>Most apps should implement a routing module for consistency.\nIt keeps the code clean when configuration becomes complex.\nIt makes testing the feature module easier.\nIts existence calls attention to the fact that a module is routed.\nIt is where developers expect to find and expand routing configuration.</p>\n<a id=\"heroes-feature\"></a>\n<h2 id=\"milestone-3-heroes-feature\">Milestone 3: Heroes feature<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#milestone-3-heroes-feature\"><i class=\"material-icons\">link</i></a></h2>\n<p>This milestone covers the following:</p>\n<ul>\n<li>Organizing the app and routes into feature areas using modules.</li>\n<li>Navigating imperatively from one component to another.</li>\n<li>Passing required and optional information in route parameters.</li>\n</ul>\n<p>This sample app recreates the heroes feature in the \"Services\" section of the <a href=\"tutorial/toh-pt4\" title=\"Tour of Heroes: Services\">Tour of Heroes tutorial</a>, and reuses much of the code from the <live-example name=\"toh-pt4\" title=\"Tour of Heroes: Services example code\"></live-example>.</p>\n<!-- KW - this gif isn't ideal for accessibility. Would like to remove it.-->\n<!-- Here's how the user will experience this version of the app:\n\n\n<div class=\"lightbox\">\n <img src='generated/images/guide/router/router-2-anim.gif' alt=\"App in action\">\n</div> -->\n<p>A typical application has multiple feature areas, each dedicated to a particular business purpose with its own folder.</p>\n<p>This section shows you how refactor the app into different feature modules, import them into the main module and navigate among them.</p>\n<a id=\"heroes-functionality\"></a>\n<h3 id=\"add-heroes-functionality\">Add heroes functionality<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#add-heroes-functionality\"><i class=\"material-icons\">link</i></a></h3>\n<p>Follow these steps:</p>\n<ul>\n<li>To manage the heroes, create a <code>HeroesModule</code> with routing in the heroes folder and register it with the root <code>AppModule</code>.</li>\n</ul>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate module heroes/heroes --module app --flat --routing\n</code-example>\n<ul>\n<li>\n<p>Move the placeholder <code>hero-list</code> folder that's in the <code>app</code> folder into the <code>heroes</code> folder.</p>\n</li>\n<li>\n<p>Copy the contents of the <code>heroes/heroes.component.html</code> from\nthe <live-example name=\"toh-pt4\" title=\"Tour of Heroes: Services example code\">\"Services\" tutorial</live-example> into the <code>hero-list.component.html</code> template.</p>\n<ul>\n<li>Re-label the <code><h2></code> to <code><h2>HEROES</h2></code>.</li>\n<li>Delete the <code><app-hero-detail></code> component at the bottom of the template.</li>\n</ul>\n</li>\n<li>\n<p>Copy the contents of the <code>heroes/heroes.component.css</code> from the live example into the <code>hero-list.component.css</code> file.</p>\n</li>\n<li>\n<p>Copy the contents of the <code>heroes/heroes.component.ts</code> from the live example into the <code>hero-list.component.ts</code> file.</p>\n<ul>\n<li>Change the component class name to <code>HeroListComponent</code>.</li>\n<li>Change the <code>selector</code> to <code>app-hero-list</code>.</li>\n</ul>\n</li>\n</ul>\n<div class=\"alert is-helpful\">\n<p> Selectors are not required for routed components because components are dynamically inserted when the page is rendered. However, they are useful for identifying and targeting them in your HTML element tree.</p>\n</div>\n<ul>\n<li>Copy the <code>hero-detail</code> folder, the <code>hero.ts</code>, <code>hero.service.ts</code>, and <code>mock-heroes.ts</code> files into the <code>heroes</code> subfolder.</li>\n<li>Copy the <code>message.service.ts</code> into the <code>src/app</code> folder.</li>\n<li>Update the relative path import to the <code>message.service</code> in the <code>hero.service.ts</code> file.</li>\n</ul>\n<p>Next, update the <code>HeroesModule</code> metadata.</p>\n<ul>\n<li>Import and add the <code>HeroDetailComponent</code> and <code>HeroListComponent</code> to the <code>declarations</code> array in the <code>HeroesModule</code>.</li>\n</ul>\n<code-example path=\"router/src/app/heroes/heroes.module.ts\" header=\"src/app/heroes/heroes.module.ts\">\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';\nimport { <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a> } from '@angular/forms';\n\nimport { HeroListComponent } from './hero-list/hero-list.component';\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\n\nimport { HeroesRoutingModule } from './heroes-routing.module';\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 <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>,\n HeroesRoutingModule\n ],\n declarations: [\n HeroListComponent,\n HeroDetailComponent\n ]\n})\nexport class HeroesModule {}\n\n\n</code-example>\n<p>The hero management file structure is as follows:</p>\n<div class=\"filetree\">\n <div class=\"file\">\n src/app/heroes\n </div>\n <div class=\"children\">\n <div class=\"file\">\n hero-detail\n </div>\n <div class=\"children\">\n <div class=\"file\">\n hero-detail.component.css\n </div>\n <div class=\"file\">\n hero-detail.component.html\n </div>\n <div class=\"file\">\n hero-detail.component.ts\n </div>\n </div>\n <div class=\"file\">\n hero-list\n </div>\n <div class=\"children\">\n <div class=\"file\">\n hero-list.component.css\n </div>\n <div class=\"file\">\n hero-list.component.html\n </div>\n <div class=\"file\">\n hero-list.component.ts\n </div>\n </div>\n <div class=\"file\">\n hero.service.ts\n </div>\n <div class=\"file\">\n hero.ts\n </div>\n <div class=\"file\">\n heroes-routing.module.ts\n </div>\n <div class=\"file\">\n heroes.module.ts\n </div>\n <div class=\"file\">\n mock-heroes.ts\n </div>\n </div>\n </div>\n</div>\n<a id=\"hero-routing-requirements\"></a>\n<h4 id=\"hero-feature-routing-requirements\">Hero feature routing requirements<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#hero-feature-routing-requirements\"><i class=\"material-icons\">link</i></a></h4>\n<p>The heroes feature has two interacting components, the hero list and the hero detail.\nWhen you navigate to list view, it gets a list of heroes and displays them.\nWhen you click on a hero, the detail view has to display that particular hero.</p>\n<p>You tell the detail view which hero to display by including the selected hero's id in the route URL.</p>\n<p>Import the hero components from their new locations in the <code>src/app/heroes/</code> folder and define the two hero routes.</p>\n<p>Now that you have routes for the <code>Heroes</code> module, register them with the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> via the <code><a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a></code> as you did in the <code>AppRoutingModule</code>, with an important difference.</p>\n<p>In the <code>AppRoutingModule</code>, you used the static <code><a href=\"api/router/RouterModule#forRoot\" class=\"code-anchor\">RouterModule.forRoot()</a></code> method to register the routes and application level service providers.\nIn a feature module you use the static <code>forChild()</code> method.</p>\n<div class=\"alert is-helpful\">\n<p>Only call <code><a href=\"api/router/RouterModule#forRoot\" class=\"code-anchor\">RouterModule.forRoot()</a></code> in the root <code>AppRoutingModule</code>\n(or the <code>AppModule</code> if that's where you register top level application routes).\nIn any other module, you must call the <code><a href=\"api/router/RouterModule#forChild\" class=\"code-anchor\">RouterModule.forChild()</a></code> method to register additional routes.</p>\n</div>\n<p>The updated <code>HeroesRoutingModule</code> looks like this:</p>\n<code-example path=\"router/src/app/heroes/heroes-routing.module.1.ts\" header=\"src/app/heroes/heroes-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 { HeroListComponent } from './hero-list/hero-list.component';\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\n\nconst heroesRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'heroes', component: HeroListComponent },\n { path: 'hero/:id', component: HeroDetailComponent }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(heroesRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class HeroesRoutingModule { }\n\n</code-example>\n<div class=\"alert is-helpful\">\n<p>Consider giving each feature module its own route configuration file.\nThough the feature routes are currently minimal, routes have a tendency to grow more complex even in small apps.</p>\n</div>\n<a id=\"remove-duplicate-hero-routes\"></a>\n<h4 id=\"remove-duplicate-hero-routes\">Remove duplicate hero routes<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#remove-duplicate-hero-routes\"><i class=\"material-icons\">link</i></a></h4>\n<p>The hero routes are currently defined in two places: in the <code>HeroesRoutingModule</code>,\nby way of the <code>HeroesModule</code>, and in the <code>AppRoutingModule</code>.</p>\n<p>Routes provided by feature modules are combined together into their imported module's routes by the router.\nThis allows you to continue defining the feature module routes without modifying the main route configuration.</p>\n<p>Remove the <code>HeroListComponent</code> import and the <code>/heroes</code> route from the <code>app-routing.module.ts</code>.</p>\n<p>Leave the default and the wildcard routes as these are still in use at the top level of the application.</p>\n<code-example path=\"router/src/app/app-routing.module.2.ts\" header=\"src/app/app-routing.module.ts (v2)\">\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 { CrisisListComponent } from './crisis-list/crisis-list.component';\n// import { HeroListComponent } from './hero-list/hero-list.component'; // <-- delete this line\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\n\nconst appRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'crisis-center', component: CrisisListComponent },\n // { path: 'heroes', component: HeroListComponent }, // <-- delete this line\n { path: '', redirectTo: '/heroes', pathMatch: 'full' },\n { path: '**', component: PageNotFoundComponent }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forRoot(\n appRoutes,\n { enableTracing: true } // <-- debugging purposes only\n )\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class AppRoutingModule {}\n\n\n</code-example>\n<a id=\"merge-hero-routes\"></a>\n<h4 id=\"remove-heroes-declarations\">Remove heroes declarations<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#remove-heroes-declarations\"><i class=\"material-icons\">link</i></a></h4>\n<p>Because the <code>HeroesModule</code> now provides the <code>HeroListComponent</code>, remove it from the <code>AppModule</code>'s <code>declarations</code> array.\nNow that you have a separate <code>HeroesModule</code>, you can evolve the hero feature with more components and different routes.</p>\n<p>After these steps, the <code>AppModule</code> should look like this:</p>\n<code-example path=\"router/src/app/app.module.3.ts\" header=\"src/app/app.module.ts\" region=\"remove-heroes\">\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';\nimport { AppComponent } from './app.component';\nimport { AppRoutingModule } from './app-routing.module';\nimport { HeroesModule } from './heroes/heroes.module';\n\nimport { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\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 HeroesModule,\n AppRoutingModule\n ],\n declarations: [\n AppComponent,\n CrisisListComponent,\n PageNotFoundComponent\n ],\n bootstrap: [ AppComponent ]\n})\nexport class AppModule { }\n\n</code-example>\n<a id=\"routing-module-order\"></a>\n<h3 id=\"module-import-order\">Module import order<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#module-import-order\"><i class=\"material-icons\">link</i></a></h3>\n<p>Notice that in the module <code>imports</code> array, the <code>AppRoutingModule</code> is last and comes <em>after</em> the <code>HeroesModule</code>.</p>\n<code-example path=\"router/src/app/app.module.3.ts\" region=\"module-imports\" header=\"src/app/app.module.ts (module-imports)\">\nimports: [\n <a href=\"api/platform-browser/BrowserModule\" class=\"code-anchor\">BrowserModule</a>,\n <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>,\n HeroesModule,\n AppRoutingModule\n],\n\n</code-example>\n<p>The order of route configuration is important because the router accepts the first route that matches a navigation request path.</p>\n<p>When all routes were in one <code>AppRoutingModule</code>, you put the default and <a href=\"guide/router-tutorial-toh#wildcard\">wildcard</a> routes last, after the <code>/heroes</code> route, so that the router had a chance to match a URL to the <code>/heroes</code> route <em>before</em> hitting the wildcard route and navigating to \"Page not found\".</p>\n<p>Each routing module augments the route configuration in the order of import.\nIf you listed <code>AppRoutingModule</code> first, the wildcard route would be registered <em>before</em> the hero routes.\nThe wildcard route—which matches <em>every</em> URL—would intercept the attempt to navigate to a hero route.</p>\n<div class=\"alert is-helpful\">\n<p>Reverse the routing modules to see a click of the heroes link resulting in \"Page not found\".\nLearn about inspecting the runtime router configuration <a href=\"guide/router-tutorial-toh#inspect-config\" title=\"Inspect the router config\">below</a>.</p>\n</div>\n<h3 id=\"route-parameters\">Route Parameters<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#route-parameters\"><i class=\"material-icons\">link</i></a></h3>\n<a id=\"route-def-with-parameter\"></a>\n<h4 id=\"route-definition-with-a-parameter\">Route definition with a parameter<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#route-definition-with-a-parameter\"><i class=\"material-icons\">link</i></a></h4>\n<p>Return to the <code>HeroesRoutingModule</code> and look at the route definitions again.\nThe route to <code>HeroDetailComponent</code> has an <code>:id</code> token in the path.</p>\n<code-example path=\"router/src/app/heroes/heroes-routing.module.1.ts\" header=\"src/app/heroes/heroes-routing.module.ts (excerpt)\" region=\"hero-detail-route\">\n{ path: 'hero/:id', component: HeroDetailComponent }\n\n</code-example>\n<p>The <code>:id</code> token creates a slot in the path for a Route Parameter.\nIn this case, this configuration causes the router to insert the <code>id</code> of a hero into that slot.</p>\n<p>If you tell the router to navigate to the detail component and display \"Magneta\", you expect a hero id to appear in the browser URL like this:</p>\n<code-example format=\"nocode\">\n localhost:4200/hero/15\n\n</code-example>\n<p>If a user enters that URL into the browser address bar, the router should recognize the pattern and go to the same \"Magneta\" detail view.</p>\n<div class=\"callout is-helpful\">\n<header>\n Route parameter: Required or optional?\n</header>\n<p>Embedding the route parameter token, <code>:id</code>, in the route definition path is a good choice for this scenario because the <code>id</code> is <em>required</em> by the <code>HeroDetailComponent</code> and because the value <code>15</code> in the path clearly distinguishes the route to \"Magneta\" from a route for some other hero.</p>\n</div>\n<a id=\"route-parameters\"></a>\n<h4 id=\"setting-the-route-parameters-in-the-list-view\">Setting the route parameters in the list view<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#setting-the-route-parameters-in-the-list-view\"><i class=\"material-icons\">link</i></a></h4>\n<p>After navigating to the <code>HeroDetailComponent</code>, you expect to see the details of the selected hero.\nYou need two pieces of information: the routing path to the component and the hero's <code>id</code>.</p>\n<p>Accordingly, the <em>link parameters array</em> has two items: the routing <em>path</em> and a <em>route parameter</em> that specifies the\n<code>id</code> of the selected hero.</p>\n<code-example path=\"router/src/app/heroes/hero-list/hero-list.component.1.html\" header=\"src/app/heroes/hero-list/hero-list.component.html (link-parameters-array)\" region=\"link-parameters-array\">\n<a [<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]=\"['/hero', hero.id]\">\n\n</code-example>\n<p>The router composes the destination URL from the array like this: <code>localhost:4200/hero/15</code>.</p>\n<p>The router extracts the route parameter (<code>id:15</code>) from the URL and supplies it to\nthe <code>HeroDetailComponent</code> via the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> service.</p>\n<a id=\"activated-route-in-action\"></a>\n<h3 id=\"activated-route-in-action\"><code>Activated <a href=\"api/router/Route\" class=\"code-anchor\">Route</a></code> in action<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#activated-route-in-action\"><i class=\"material-icons\">link</i></a></h3>\n<p>Import the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code>, <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code>, and <code><a href=\"api/router/ParamMap\" class=\"code-anchor\">ParamMap</a></code> tokens from the router package.</p>\n<code-example path=\"router/src/app/heroes/hero-detail/hero-detail.component.1.ts\" header=\"src/app/heroes/hero-detail/hero-detail.component.ts (activated route)\" region=\"imports\">\nimport { <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>, <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>, <a href=\"api/router/ParamMap\" class=\"code-anchor\">ParamMap</a> } from '@angular/router';\n\n</code-example>\n<p>Import the <code>switchMap</code> operator because you need it later to process the <code>Observable</code> route parameters.</p>\n<code-example path=\"router/src/app/heroes/hero-detail/hero-detail.component.3.ts\" header=\"src/app/heroes/hero-detail/hero-detail.component.ts (switchMap operator import)\" region=\"rxjs-operator-import\">\nimport { switchMap } from 'rxjs/operators';\n\n</code-example>\n<a id=\"hero-detail-ctor\"></a>\n<p>Add the services as private variables to the constructor so that Angular injects them (makes them visible to the component).</p>\n<code-example path=\"router/src/app/heroes/hero-detail/hero-detail.component.3.ts\" header=\"src/app/heroes/hero-detail/hero-detail.component.ts (constructor)\" region=\"ctor\">\nconstructor(\n private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>,\n private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>,\n private service: HeroService\n) {}\n\n</code-example>\n<p>In the <code>ngOnInit()</code> method, use the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> service to retrieve the parameters for the route, pull the hero <code>id</code> from the parameters, and retrieve the hero to display.</p>\n<code-example path=\"router/src/app/heroes/hero-detail/hero-detail.component.3.ts\" header=\"src/app/heroes/hero-detail/hero-detail.component.ts (ngOnInit)\" region=\"ngOnInit\">\nngOnInit() {\n this.hero$ = this.route.paramMap.pipe(\n switchMap((params: <a href=\"api/router/ParamMap\" class=\"code-anchor\">ParamMap</a>) =>\n this.service.getHero(params.get('id')))\n );\n}\n\n</code-example>\n<p>When the map changes, <code>paramMap</code> gets the <code>id</code> parameter from the changed parameters.</p>\n<p>Then you tell the <code>HeroService</code> to fetch the hero with that <code>id</code> and return the result of the <code>HeroService</code> request.</p>\n<p>The <code>switchMap</code> operator does two things. It flattens the <code>Observable<Hero></code> that <code>HeroService</code> returns and cancels previous pending requests.\nIf the user re-navigates to this route with a new <code>id</code> while the <code>HeroService</code> is still retrieving the old <code>id</code>, <code>switchMap</code> discards that old request and returns the hero for the new <code>id</code>.</p>\n<p><code><a href=\"api/common/AsyncPipe\" class=\"code-anchor\">AsyncPipe</a></code> handles the observable subscription and the component's <code>hero</code> property will be (re)set with the retrieved hero.</p>\n<h4 id=\"parammap-api\"><em>ParamMap</em> API<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#parammap-api\"><i class=\"material-icons\">link</i></a></h4>\n<p>The <code><a href=\"api/router/ParamMap\" class=\"code-anchor\">ParamMap</a></code> API is inspired by the <a href=\"https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams\">URLSearchParams interface</a>.\nIt provides methods to handle parameter access for both route parameters (<code>paramMap</code>) and query parameters (<code>queryParamMap</code>).</p>\n<table>\n <tbody><tr>\n <th>\n Member\n </th>\n <th>\n Description\n </th>\n </tr>\n <tr>\n <td>\n <code>has(name)</code>\n </td>\n <td>\n<p> Returns <code>true</code> if the parameter name is in the map of parameters.</p>\n </td>\n </tr>\n <tr>\n <td>\n <code>get(name)</code>\n </td>\n <td>\n<p> Returns the parameter name value (a <code>string</code>) if present, or <code>null</code> if the parameter name is not in the map. Returns the <em>first</em> element if the parameter value is actually an array of values.</p>\n </td>\n </tr>\n <tr>\n <td>\n <code>getAll(name)</code>\n </td>\n <td>\n<p> Returns a <code>string array</code> of the parameter name value if found, or an empty <code>array</code> if the parameter name value is not in the map. Use <code>getAll</code> when a single parameter could have multiple values.</p>\n </td>\n </tr>\n <tr>\n <td>\n <code>keys</code>\n </td>\n <td>\n<p> Returns a <code>string array</code> of all parameter names in the map.</p>\n </td>\n </tr>\n</tbody></table>\n<a id=\"reuse\"></a>\n<h4 id=\"observable-parammap-and-component-reuse\">Observable <i>paramMap</i> and component reuse<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#observable-parammap-and-component-reuse\"><i class=\"material-icons\">link</i></a></h4>\n<p>In this example, you retrieve the route parameter map from an <code>Observable</code>.\nThat implies that the route parameter map can change during the lifetime of this component.</p>\n<p>By default, the router re-uses a component instance when it re-navigates to the same component type\nwithout visiting a different component first. The route parameters could change each time.</p>\n<p>Suppose a parent component navigation bar had \"forward\" and \"back\" buttons\nthat scrolled through the list of heroes.\nEach click navigated imperatively to the <code>HeroDetailComponent</code> with the next or previous <code>id</code>.</p>\n<p>You wouldn't want the router to remove the current <code>HeroDetailComponent</code> instance from the DOM only to re-create it for the next <code>id</code> as this would re-render the view.\nFor better UX, the router re-uses the same component instance and updates the parameter.</p>\n<p>Since <code>ngOnInit()</code> is only called once per component instantiation, you can detect when the route parameters change from <em>within the same instance</em> using the observable <code>paramMap</code> property.</p>\n<div class=\"alert is-helpful\">\n<p>When subscribing to an observable in a component, you almost always unsubscribe when the component is destroyed.</p>\n<p>However, <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> observables are among the exceptions because <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> and its observables are insulated from the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> itself.\nThe <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> destroys a routed component when it is no longer needed along with the injected <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code>.</p>\n</div>\n<a id=\"snapshot\"></a>\n<h4 id=\"snapshot-the-no-observable-alternative\"><code>snapshot</code>: the no-observable alternative<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#snapshot-the-no-observable-alternative\"><i class=\"material-icons\">link</i></a></h4>\n<p>This application won't re-use the <code>HeroDetailComponent</code>.\nThe user always returns to the hero list to select another hero to view.\nThere's no way to navigate from one hero detail to another hero detail without visiting the list component in between.\nTherefore, the router creates a new <code>HeroDetailComponent</code> instance every time.</p>\n<p>When you know for certain that a <code>HeroDetailComponent</code> instance will never be re-used, you can use <code>snapshot</code>.</p>\n<p><code>route.snapshot</code> provides the initial value of the route parameter map.\nYou can access the parameters directly without subscribing or adding observable operators as in the following:</p>\n<code-example path=\"router/src/app/heroes/hero-detail/hero-detail.component.2.ts\" header=\"src/app/heroes/hero-detail/hero-detail.component.ts (ngOnInit snapshot)\" region=\"snapshot\">\nngOnInit() {\n const id = this.route.snapshot.paramMap.get('id');\n\n this.hero$ = this.service.getHero(id);\n}\n\n</code-example>\n<div class=\"alert is-helpful\">\n<p><code>snapshot</code> only gets the initial value of the parameter map with this technique.\nUse the observable <code>paramMap</code> approach if there's a possibility that the router could re-use the component.\nThis tutorial sample app uses with the observable <code>paramMap</code>.</p>\n</div>\n<a id=\"nav-to-list\"></a>\n<h3 id=\"navigating-back-to-the-list-component\">Navigating back to the list component<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#navigating-back-to-the-list-component\"><i class=\"material-icons\">link</i></a></h3>\n<p>The <code>HeroDetailComponent</code> \"Back\" button uses the <code>gotoHeroes()</code> method that navigates imperatively back to the <code>HeroListComponent</code>.</p>\n<p>The router <code>navigate()</code> method takes the same one-item <em>link parameters array</em> that you can bind to a <code>[<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]</code> directive.\nIt holds the path to the <code>HeroListComponent</code>:</p>\n<code-example path=\"router/src/app/heroes/hero-detail/hero-detail.component.1.ts\" header=\"src/app/heroes/hero-detail/hero-detail.component.ts (excerpt)\" region=\"gotoHeroes\">\ngotoHeroes() {\n this.router.navigate(['/heroes']);\n}\n\n</code-example>\n<a id=\"optional-route-parameters\"></a>\n<h4 id=\"route-parameters-required-or-optional\">Route Parameters: Required or optional?<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#route-parameters-required-or-optional\"><i class=\"material-icons\">link</i></a></h4>\n<p>Use <a href=\"guide/router-tutorial-toh#route-parameters\">route parameters</a> to specify a required parameter value within the route URL\nas you do when navigating to the <code>HeroDetailComponent</code> in order to view the hero with <code>id</code> 15:</p>\n<code-example format=\"nocode\">\n localhost:4200/hero/15\n\n</code-example>\n<p>You can also add optional information to a route request.\nFor example, when returning to the <code>hero-detail.component.ts</code> list from the hero detail view, it would be nice if the viewed hero were preselected in the list.</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/router/selected-hero.png\" alt=\"Selected hero\" width=\"336\" height=\"110\">\n</div>\n<p>You implement this feature by including the viewed hero's <code>id</code> in the URL as an optional parameter when returning from the <code>HeroDetailComponent</code>.</p>\n<p>Optional information can also include other forms such as:</p>\n<ul>\n<li>Loosely structured search criteria; for example, <code>name='wind*'</code>.</li>\n<li>Multiple values; for example, <code>after='12/31/2015' & before='1/1/2017'</code>—in no\nparticular order—<code>before='1/1/2017' & after='12/31/2015'</code>— in a\nvariety of formats—<code>during='currentYear'</code>.</li>\n</ul>\n<p>As these kinds of parameters don't fit easily in a URL path, you can use optional parameters for conveying arbitrarily complex information during navigation.\nOptional parameters aren't involved in pattern matching and afford flexibility of expression.</p>\n<p>The router supports navigation with optional parameters as well as required route parameters.\nDefine optional parameters in a separate object <em>after</em> you define the required route parameters.</p>\n<p>In general, use a required route parameter when the value is mandatory (for example, if necessary to distinguish one route path from another); and an optional parameter when the value is optional, complex, and/or multivariate.</p>\n<a id=\"optionally-selecting\"></a>\n<h4 id=\"heroes-list-optionally-selecting-a-hero\">Heroes list: optionally selecting a hero<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#heroes-list-optionally-selecting-a-hero\"><i class=\"material-icons\">link</i></a></h4>\n<p>When navigating to the <code>HeroDetailComponent</code> you specified the required <code>id</code> of the hero-to-edit in the\nroute parameter and made it the second item of the <a href=\"guide/router-tutorial-toh#link-parameters-array\"><em>link parameters array</em></a>.</p>\n<code-example path=\"router/src/app/heroes/hero-list/hero-list.component.1.html\" header=\"src/app/heroes/hero-list/hero-list.component.html (link-parameters-array)\" region=\"link-parameters-array\">\n<a [<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]=\"['/hero', hero.id]\">\n\n</code-example>\n<p>The router embedded the <code>id</code> value in the navigation URL because you had defined it as a route parameter with an <code>:id</code> placeholder token in the route <code>path</code>:</p>\n<code-example path=\"router/src/app/heroes/heroes-routing.module.1.ts\" header=\"src/app/heroes/heroes-routing.module.ts (hero-detail-route)\" region=\"hero-detail-route\">\n{ path: 'hero/:id', component: HeroDetailComponent }\n\n</code-example>\n<p>When the user clicks the back button, the <code>HeroDetailComponent</code> constructs another <em>link parameters array</em>\nwhich it uses to navigate back to the <code>HeroListComponent</code>.</p>\n<code-example path=\"router/src/app/heroes/hero-detail/hero-detail.component.1.ts\" header=\"src/app/heroes/hero-detail/hero-detail.component.ts (gotoHeroes)\" region=\"gotoHeroes\">\ngotoHeroes() {\n this.router.navigate(['/heroes']);\n}\n\n</code-example>\n<p>This array lacks a route parameter because previously you didn't need to send information to the <code>HeroListComponent</code>.</p>\n<p>Now, send the <code>id</code> of the current hero with the navigation request so that the\n<code>HeroListComponent</code> can highlight that hero in its list.</p>\n<p>Send the <code>id</code> with an object that contains an optional <code>id</code> parameter.\nFor demonstration purposes, there's an extra junk parameter (<code>foo</code>) in the object that the <code>HeroListComponent</code> should ignore.\nHere's the revised navigation statement:</p>\n<code-example path=\"router/src/app/heroes/hero-detail/hero-detail.component.3.ts\" header=\"src/app/heroes/hero-detail/hero-detail.component.ts (go to heroes)\" region=\"gotoHeroes\">\ngotoHeroes(hero: Hero) {\n const heroId = hero ? hero.id : null;\n // Pass along the hero id if available\n // so that the HeroList component can select that hero.\n // Include a junk 'foo' property for fun.\n this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]);\n}\n\n</code-example>\n<p>The application still works. Clicking \"back\" returns to the hero list view.</p>\n<p>Look at the browser address bar.</p>\n<p>It should look something like this, depending on where you run it:</p>\n<code-example language=\"bash\">\n localhost:4200/heroes;id=15;foo=foo\n\n</code-example>\n<p>The <code>id</code> value appears in the URL as (<code>;id=15;foo=foo</code>), not in the URL path.\nThe path for the \"Heroes\" route doesn't have an <code>:id</code> token.</p>\n<p>The optional route parameters are not separated by \"?\" and \"&\" as they would be in the URL query string.\nThey are separated by semicolons \";\".\nThis is matrix URL notation.</p>\n<div class=\"alert is-helpful\">\n<p>Matrix URL notation is an idea first introduced in a <a href=\"https://www.w3.org/DesignIssues/MatrixURIs.html\">1996 proposal</a> by the founder of the web, Tim Berners-Lee.</p>\n<p>Although matrix notation never made it into the HTML standard, it is legal and it became popular among browser routing systems as a way to isolate parameters belonging to parent and child routes.\nAs such, the Router provides support for the matrix notation across browsers.</p>\n</div>\n<a id=\"route-parameters-activated-route\"></a>\n<h3 id=\"route-parameters-in-the-activatedroute-service\">Route parameters in the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> service<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#route-parameters-in-the-activatedroute-service\"><i class=\"material-icons\">link</i></a></h3>\n<p>In its current state of development, the list of heroes is unchanged.\nNo hero row is highlighted.</p>\n<p>The <code>HeroListComponent</code> needs code that expects parameters.</p>\n<p>Previously, when navigating from the <code>HeroListComponent</code> to the <code>HeroDetailComponent</code>,\nyou subscribed to the route parameter map <code>Observable</code> and made it available to the <code>HeroDetailComponent</code>\nin the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> service.\nYou injected that service in the constructor of the <code>HeroDetailComponent</code>.</p>\n<p>This time you'll be navigating in the opposite direction, from the <code>HeroDetailComponent</code> to the <code>HeroListComponent</code>.</p>\n<p>First, extend the router import statement to include the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> service symbol:</p>\n<code-example path=\"router/src/app/heroes/hero-list/hero-list.component.ts\" header=\"src/app/heroes/hero-list/hero-list.component.ts (import)\" region=\"import-router\">\nimport { <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a> } from '@angular/router';\n\n</code-example>\n<p>Import the <code>switchMap</code> operator to perform an operation on the <code>Observable</code> of route parameter map.</p>\n<code-example path=\"router/src/app/heroes/hero-list/hero-list.component.ts\" header=\"src/app/heroes/hero-list/hero-list.component.ts (rxjs imports)\" region=\"rxjs-imports\">\nimport { Observable } from 'rxjs';\nimport { switchMap } from 'rxjs/operators';\n\n</code-example>\n<p>Inject the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> in the <code>HeroListComponent</code> constructor.</p>\n<code-example path=\"router/src/app/heroes/hero-list/hero-list.component.ts\" header=\"src/app/heroes/hero-list/hero-list.component.ts (constructor and ngOnInit)\" region=\"ctor\">\nexport class HeroListComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n heroes$: Observable<Hero[]>;\n selectedId: number;\n\n constructor(\n private service: HeroService,\n private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>\n ) {}\n\n ngOnInit() {\n this.heroes$ = this.route.paramMap.pipe(\n switchMap(params => {\n // (+) before `params.get()` turns the string into a number\n this.selectedId = +params.get('id');\n return this.service.getHeroes();\n })\n );\n }\n}\n\n</code-example>\n<p>The <code><a href=\"api/router/ActivatedRoute#paramMap\" class=\"code-anchor\">ActivatedRoute.paramMap</a></code> property is an <code>Observable</code> map of route parameters.\nThe <code>paramMap</code> emits a new map of values that includes <code>id</code> when the user navigates to the component.\nIn <code>ngOnInit()</code> you subscribe to those values, set the <code>selectedId</code>, and get the heroes.</p>\n<p>Update the template with a <a href=\"guide/attribute-binding#class-binding\">class binding</a>.\nThe binding adds the <code>selected</code> CSS class when the comparison returns <code>true</code> and removes it when <code>false</code>.\nLook for it within the repeated <code><li></code> tag as shown here:</p>\n<code-example path=\"router/src/app/heroes/hero-list/hero-list.component.html\" header=\"src/app/heroes/hero-list/hero-list.component.html\">\n<h2>HEROES</h2>\n<ul class=\"heroes\">\n <li *<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a>=\"let hero of heroes$ | async\"\n [class.selected]=\"hero.id === selectedId\">\n <a [<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]=\"['/hero', hero.id]\">\n <span class=\"badge\">{{ hero.id }}</span>{{ hero.name }}\n </a>\n </li>\n</ul>\n\n<button <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/sidekicks\">Go to sidekicks</button>\n\n</code-example>\n<p>Add some styles to apply when the list item is selected.</p>\n<code-example path=\"router/src/app/heroes/hero-list/hero-list.component.css\" region=\"selected\" header=\"src/app/heroes/hero-list/hero-list.component.css\">\n.heroes li.selected {\n background-color: #CFD8DC;\n color: white;\n}\n.heroes li.selected:hover {\n background-color: #BBD8DC;\n}\n\n</code-example>\n<p>When the user navigates from the heroes list to the \"Magneta\" hero and back, \"Magneta\" appears selected:</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/router/selected-hero.png\" alt=\"Selected List\" width=\"336\" height=\"110\">\n</div>\n<p>The optional <code>foo</code> route parameter is harmless and the router continues to ignore it.</p>\n<a id=\"route-animation\"></a>\n<h3 id=\"adding-routable-animations\">Adding routable animations<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#adding-routable-animations\"><i class=\"material-icons\">link</i></a></h3>\n<p>This section shows you how to add some <a href=\"guide/animations\">animations</a> to the <code>HeroDetailComponent</code>.</p>\n<p>First, import the <code><a href=\"api/platform-browser/animations/BrowserAnimationsModule\" class=\"code-anchor\">BrowserAnimationsModule</a></code> and add it to the <code>imports</code> array:</p>\n<code-example path=\"router/src/app/app.module.ts\" header=\"src/app/app.module.ts (animations-module)\" region=\"animations-module\">\nimport { <a href=\"api/platform-browser/animations/BrowserAnimationsModule\" class=\"code-anchor\">BrowserAnimationsModule</a> } from '@angular/platform-browser/animations';\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n <a href=\"api/platform-browser/animations/BrowserAnimationsModule\" class=\"code-anchor\">BrowserAnimationsModule</a>,\n ],\n})\n\n</code-example>\n<p>Next, add a <code>data</code> object to the routes for <code>HeroListComponent</code> and <code>HeroDetailComponent</code>.\nTransitions are based on <code>states</code> and you use the <code><a href=\"api/animations/animation\" class=\"code-anchor\">animation</a></code> data from the route to provide a named animation <code><a href=\"api/animations/state\" class=\"code-anchor\">state</a></code> for the transitions.</p>\n<code-example path=\"router/src/app/heroes/heroes-routing.module.2.ts\" header=\"src/app/heroes/heroes-routing.module.ts (animation data)\">\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 { HeroListComponent } from './hero-list/hero-list.component';\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\n\nconst heroesRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'heroes', component: HeroListComponent, data: { <a href=\"api/animations/animation\" class=\"code-anchor\">animation</a>: 'heroes' } },\n { path: 'hero/:id', component: HeroDetailComponent, data: { <a href=\"api/animations/animation\" class=\"code-anchor\">animation</a>: 'hero' } }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(heroesRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class HeroesRoutingModule { }\n\n</code-example>\n<p>Create an <code>animations.ts</code> file in the root <code>src/app/</code> folder. The contents look like this:</p>\n<code-example path=\"router/src/app/animations.ts\" header=\"src/app/animations.ts (excerpt)\">\nimport {\n <a href=\"api/animations/trigger\" class=\"code-anchor\">trigger</a>, <a href=\"api/animations/animateChild\" class=\"code-anchor\">animateChild</a>, group,\n <a href=\"api/animations/transition\" class=\"code-anchor\">transition</a>, <a href=\"api/animations/animate\" class=\"code-anchor\">animate</a>, <a href=\"api/animations/style\" class=\"code-anchor\">style</a>, <a href=\"api/animations/query\" class=\"code-anchor\">query</a>\n} from '@angular/animations';\n\n\n// Routable animations\nexport const slideInAnimation =\n <a href=\"api/animations/trigger\" class=\"code-anchor\">trigger</a>('routeAnimation', [\n <a href=\"api/animations/transition\" class=\"code-anchor\">transition</a>('heroes <=> hero', [\n <a href=\"api/animations/style\" class=\"code-anchor\">style</a>({ position: 'relative' }),\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':enter, :leave', [\n <a href=\"api/animations/style\" class=\"code-anchor\">style</a>({\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%'\n })\n ]),\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':enter', [\n <a href=\"api/animations/style\" class=\"code-anchor\">style</a>({ left: '-100%'})\n ]),\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':leave', <a href=\"api/animations/animateChild\" class=\"code-anchor\">animateChild</a>()),\n group([\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':leave', [\n <a href=\"api/animations/animate\" class=\"code-anchor\">animate</a>('300ms ease-out', <a href=\"api/animations/style\" class=\"code-anchor\">style</a>({ left: '100%'}))\n ]),\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':enter', [\n <a href=\"api/animations/animate\" class=\"code-anchor\">animate</a>('300ms ease-out', <a href=\"api/animations/style\" class=\"code-anchor\">style</a>({ left: '0%'}))\n ])\n ]),\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':enter', <a href=\"api/animations/animateChild\" class=\"code-anchor\">animateChild</a>()),\n ])\n ]);\n\n\n</code-example>\n<p>This file does the following:</p>\n<ul>\n<li>\n<p>Imports the animation symbols that build the animation triggers, control state, and manage transitions between states.</p>\n</li>\n<li>\n<p>Exports a constant named <code>slideInAnimation</code> set to an animation trigger named <code>routeAnimation</code>.</p>\n</li>\n<li>\n<p>Defines one transition when switching back and forth from the <code>heroes</code> and <code>hero</code> routes to ease the component in from the left of the screen as it enters the application view (<code>:enter</code>), the other to animate the component to the right as it leaves the application view (<code>:leave</code>).</p>\n</li>\n</ul>\n<p>Back in the <code>AppComponent</code>, import the <code><a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a></code> token from the <code>@angular/router</code> package and the <code>slideInAnimation</code> from <code>'./animations.ts</code>.</p>\n<p>Add an <code>animations</code> array to the <code>@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a></code> metadata that contains the <code>slideInAnimation</code>.</p>\n<code-example path=\"router/src/app/app.component.2.ts\" header=\"src/app/app.component.ts (animations)\" region=\"animation-imports\">\nimport { <a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a> } from '@angular/router';\nimport { slideInAnimation } from './animations';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-root',\n templateUrl: 'app.component.html',\n styleUrls: ['app.component.css'],\n animations: [ slideInAnimation ]\n})\n\n</code-example>\n<p>In order to use the routable animations, wrap the <code><a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a></code> inside an element, use the <code>@routeAnimation</code> trigger, and bind it to the element.</p>\n<p>For the <code>@routeAnimation</code> transitions to key off states, provide it with the <code>data</code> from the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code>.\nThe <code><a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a></code> is exposed as an <code>outlet</code> template variable, so you bind a reference to the router outlet.\nThis example uses a variable of <code>routerOutlet</code>.</p>\n<code-example path=\"router/src/app/app.component.2.html\" header=\"src/app/app.component.html (router outlet)\">\n<h1>Angular <a href=\"api/router/Router\" class=\"code-anchor\">Router</a></h1>\n<nav>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/crisis-center\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Crisis Center</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/heroes\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Heroes</a>\n</nav>\n<div [@routeAnimation]=\"getAnimationData(routerOutlet)\">\n <<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a> #routerOutlet=\"outlet\"></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n</div>\n\n</code-example>\n<p>The <code>@routeAnimation</code> property is bound to the <code>getAnimationData()</code> with the provided <code>routerOutlet</code> reference, so the next step is to define that function in the <code>AppComponent</code>.\nThe <code>getAnimationData()</code> function returns the animation property from the <code>data</code> provided through the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code>. The <code><a href=\"api/animations/animation\" class=\"code-anchor\">animation</a></code> property matches the <code><a href=\"api/animations/transition\" class=\"code-anchor\">transition</a></code> names you used in the <code>slideInAnimation</code> defined in <code>animations.ts</code>.</p>\n<code-example path=\"router/src/app/app.component.2.ts\" header=\"src/app/app.component.ts (router outlet)\" region=\"function-binding\">\nexport class AppComponent {\n getAnimationData(outlet: <a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a>) {\n return outlet && outlet.activatedRouteData && outlet.activatedRouteData.animation;\n }\n}\n\n</code-example>\n<p>When switching between the two routes, the <code>HeroDetailComponent</code> and <code>HeroListComponent</code> now ease in from the left when routed to and will slide to the right when navigating away.</p>\n<a id=\"milestone-3-wrap-up\"></a>\n<h3 id=\"milestone-3-wrap-up\">Milestone 3 wrap up<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#milestone-3-wrap-up\"><i class=\"material-icons\">link</i></a></h3>\n<p>This section has covered the following:</p>\n<ul>\n<li>Organizing the app into feature areas.</li>\n<li>Navigating imperatively from one component to another.</li>\n<li>Passing information along in route parameters and subscribe to them in the component.</li>\n<li>Importing the feature area NgModule into the <code>AppModule</code>.</li>\n<li>Applying routable animations based on the page.</li>\n</ul>\n<p>After these changes, the folder structure is as follows:</p>\n<div class=\"filetree\">\n <div class=\"file\">\n angular-router-sample\n </div>\n <div class=\"children\">\n <div class=\"file\">\n src\n </div>\n <div class=\"children\">\n <div class=\"file\">\n app\n </div>\n <div class=\"children\">\n <div class=\"file\">\n crisis-list\n </div>\n <div class=\"children\">\n <div class=\"file\">\n crisis-list.component.css\n </div>\n <div class=\"file\">\n crisis-list.component.html\n </div>\n <div class=\"file\">\n crisis-list.component.ts\n </div>\n </div>\n <div class=\"file\">\n heroes\n </div>\n <div class=\"children\">\n <div class=\"file\">\n hero-detail\n </div>\n <div class=\"children\">\n <div class=\"file\">\n hero-detail.component.css\n </div>\n <div class=\"file\">\n hero-detail.component.html\n </div>\n <div class=\"file\">\n hero-detail.component.ts\n </div>\n </div>\n <div class=\"file\">\n hero-list\n </div>\n <div class=\"children\">\n <div class=\"file\">\n hero-list.component.css\n </div>\n <div class=\"file\">\n hero-list.component.html\n </div>\n <div class=\"file\">\n hero-list.component.ts\n </div>\n </div>\n <div class=\"file\">\n hero.service.ts\n </div>\n <div class=\"file\">\n hero.ts\n </div>\n <div class=\"file\">\n heroes-routing.module.ts\n </div>\n <div class=\"file\">\n heroes.module.ts\n </div>\n <div class=\"file\">\n mock-heroes.ts\n </div>\n </div>\n <div class=\"file\">\n page-not-found\n </div>\n <div class=\"children\">\n <div class=\"file\">\n<p> page-not-found.component.css</p>\n </div>\n <div class=\"file\">\n<p> page-not-found.component.html</p>\n </div>\n <div class=\"file\">\n<p> page-not-found.component.ts</p>\n </div>\n </div>\n </div>\n <div class=\"file\">\n animations.ts\n </div>\n <div class=\"file\">\n app.component.css\n </div>\n <div class=\"file\">\n app.component.html\n </div>\n <div class=\"file\">\n app.component.ts\n </div>\n <div class=\"file\">\n app.module.ts\n </div>\n <div class=\"file\">\n app-routing.module.ts\n </div>\n <div class=\"file\">\n main.ts\n </div>\n <div class=\"file\">\n message.service.ts\n </div>\n <div class=\"file\">\n index.html\n </div>\n <div class=\"file\">\n styles.css\n </div>\n <div class=\"file\">\n tsconfig.json\n </div>\n </div>\n <div class=\"file\">\n node_modules ...\n </div>\n <div class=\"file\">\n package.json\n </div>\n </div>\n</div>\n<p>Here are the relevant files for this version of the sample application.</p>\n<code-tabs>\n\n <code-pane header=\"animations.ts\" path=\"router/src/app/animations.ts\">\nimport {\n <a href=\"api/animations/trigger\" class=\"code-anchor\">trigger</a>, <a href=\"api/animations/animateChild\" class=\"code-anchor\">animateChild</a>, group,\n <a href=\"api/animations/transition\" class=\"code-anchor\">transition</a>, <a href=\"api/animations/animate\" class=\"code-anchor\">animate</a>, <a href=\"api/animations/style\" class=\"code-anchor\">style</a>, <a href=\"api/animations/query\" class=\"code-anchor\">query</a>\n} from '@angular/animations';\n\n\n// Routable animations\nexport const slideInAnimation =\n <a href=\"api/animations/trigger\" class=\"code-anchor\">trigger</a>('routeAnimation', [\n <a href=\"api/animations/transition\" class=\"code-anchor\">transition</a>('heroes <=> hero', [\n <a href=\"api/animations/style\" class=\"code-anchor\">style</a>({ position: 'relative' }),\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':enter, :leave', [\n <a href=\"api/animations/style\" class=\"code-anchor\">style</a>({\n position: 'absolute',\n top: 0,\n left: 0,\n width: '100%'\n })\n ]),\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':enter', [\n <a href=\"api/animations/style\" class=\"code-anchor\">style</a>({ left: '-100%'})\n ]),\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':leave', <a href=\"api/animations/animateChild\" class=\"code-anchor\">animateChild</a>()),\n group([\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':leave', [\n <a href=\"api/animations/animate\" class=\"code-anchor\">animate</a>('300ms ease-out', <a href=\"api/animations/style\" class=\"code-anchor\">style</a>({ left: '100%'}))\n ]),\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':enter', [\n <a href=\"api/animations/animate\" class=\"code-anchor\">animate</a>('300ms ease-out', <a href=\"api/animations/style\" class=\"code-anchor\">style</a>({ left: '0%'}))\n ])\n ]),\n <a href=\"api/animations/query\" class=\"code-anchor\">query</a>(':enter', <a href=\"api/animations/animateChild\" class=\"code-anchor\">animateChild</a>()),\n ])\n ]);\n\n\n</code-pane>\n\n <code-pane header=\"app.component.html\" path=\"router/src/app/app.component.2.html\">\n<h1>Angular <a href=\"api/router/Router\" class=\"code-anchor\">Router</a></h1>\n<nav>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/crisis-center\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Crisis Center</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/heroes\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Heroes</a>\n</nav>\n<div [@routeAnimation]=\"getAnimationData(routerOutlet)\">\n <<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a> #routerOutlet=\"outlet\"></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n</div>\n\n</code-pane>\n\n <code-pane header=\"app.component.ts\" path=\"router/src/app/app.component.2.ts\">\nimport { <a href=\"api/core/Component\" class=\"code-anchor\">Component</a> } from '@angular/core';\nimport { <a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a> } from '@angular/router';\nimport { slideInAnimation } from './animations';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-root',\n templateUrl: 'app.component.html',\n styleUrls: ['app.component.css'],\n animations: [ slideInAnimation ]\n})\nexport class AppComponent {\n getAnimationData(outlet: <a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a>) {\n return outlet && outlet.activatedRouteData && outlet.activatedRouteData.animation;\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"app.module.ts\" path=\"router/src/app/app.module.3.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';\nimport { <a href=\"api/platform-browser/animations/BrowserAnimationsModule\" class=\"code-anchor\">BrowserAnimationsModule</a> } from '@angular/platform-browser/animations';\n\nimport { AppComponent } from './app.component';\nimport { AppRoutingModule } from './app-routing.module';\nimport { HeroesModule } from './heroes/heroes.module';\n\nimport { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\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/platform-browser/animations/BrowserAnimationsModule\" class=\"code-anchor\">BrowserAnimationsModule</a>,\n <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>,\n HeroesModule,\n AppRoutingModule\n ],\n declarations: [\n AppComponent,\n CrisisListComponent,\n PageNotFoundComponent\n ],\n bootstrap: [ AppComponent ]\n})\nexport class AppModule { }\n\n</code-pane>\n\n <code-pane header=\"app-routing.module.ts\" path=\"router/src/app/app-routing.module.2.ts\" region=\"milestone3\">\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 { CrisisListComponent } from './crisis-list/crisis-list.component';\n/* . . . */\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\n\nconst appRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'crisis-center', component: CrisisListComponent },\n/* . . . */\n { path: '', redirectTo: '/heroes', pathMatch: 'full' },\n { path: '**', component: PageNotFoundComponent }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forRoot(\n appRoutes,\n { enableTracing: true } // <-- debugging purposes only\n )\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class AppRoutingModule {}\n\n</code-pane>\n\n <code-pane header=\"hero-list.component.css\" path=\"router/src/app/heroes/hero-list/hero-list.component.css\">\n/* HeroListComponent'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 background-color: #EEE;\n margin: .5em;\n padding: .3em 0;\n height: 1.6em;\n border-radius: 4px;\n}\n\n.heroes li:hover {\n color: #607D8B;\n background-color: #DDD;\n left: .1em;\n}\n\n.heroes a {\n color: #888;\n text-decoration: none;\n position: relative;\n display: block;\n}\n\n.heroes a:hover {\n color:#607D8B;\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: #607D8B;\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\nbutton {\n background-color: #eee;\n border: none;\n padding: 5px 10px;\n border-radius: 4px;\n cursor: pointer;\n font-family: Arial, sans-serif;\n}\n\nbutton:hover {\n background-color: #cfd8dc;\n}\n\nbutton.delete {\n position: relative;\n left: 194px;\n top: -32px;\n background-color: gray !important;\n color: white;\n}\n\n.heroes li.selected {\n background-color: #CFD8DC;\n color: white;\n}\n.heroes li.selected:hover {\n background-color: #BBD8DC;\n}\n\n\n</code-pane>\n\n <code-pane header=\"hero-list.component.html\" path=\"router/src/app/heroes/hero-list/hero-list.component.html\">\n<h2>HEROES</h2>\n<ul class=\"heroes\">\n <li *<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a>=\"let hero of heroes$ | async\"\n [class.selected]=\"hero.id === selectedId\">\n <a [<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]=\"['/hero', hero.id]\">\n <span class=\"badge\">{{ hero.id }}</span>{{ hero.name }}\n </a>\n </li>\n</ul>\n\n<button <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/sidekicks\">Go to sidekicks</button>\n\n</code-pane>\n\n <code-pane header=\"hero-list.component.ts\" path=\"router/src/app/heroes/hero-list/hero-list.component.ts\">\n// TODO: Feature Componetized like CrisisCenter\nimport { Observable } from 'rxjs';\nimport { switchMap } from 'rxjs/operators';\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';\n\nimport { HeroService } from '../hero.service';\nimport { Hero } from '../hero';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-hero-list',\n templateUrl: './hero-list.component.html',\n styleUrls: ['./hero-list.component.css']\n})\nexport class HeroListComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n heroes$: Observable<Hero[]>;\n selectedId: number;\n\n constructor(\n private service: HeroService,\n private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>\n ) {}\n\n ngOnInit() {\n this.heroes$ = this.route.paramMap.pipe(\n switchMap(params => {\n // (+) before `params.get()` turns the string into a number\n this.selectedId = +params.get('id');\n return this.service.getHeroes();\n })\n );\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"hero-detail.component.html\" path=\"router/src/app/heroes/hero-detail/hero-detail.component.html\">\n<h2>HEROES</h2>\n<div *<a href=\"api/common/NgIf\" class=\"code-anchor\">ngIf</a>=\"hero$ | async as hero\">\n <h3>\"{{ hero.name }}\"</h3>\n <div>\n <label>Id: </label>{{ hero.id }}</div>\n <div>\n <label>Name: </label>\n <input [(<a href=\"api/forms/NgModel\" class=\"code-anchor\">ngModel</a>)]=\"hero.name\" placeholder=\"name\"/>\n </div>\n <p>\n <button (click)=\"gotoHeroes(hero)\">Back</button>\n </p>\n</div>\n\n</code-pane>\n\n <code-pane header=\"hero-detail.component.ts\" path=\"router/src/app/heroes/hero-detail/hero-detail.component.3.ts\">\nimport { switchMap } from 'rxjs/operators';\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/Router\" class=\"code-anchor\">Router</a>, <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>, <a href=\"api/router/ParamMap\" class=\"code-anchor\">ParamMap</a> } from '@angular/router';\nimport { Observable } from 'rxjs';\n\nimport { HeroService } from '../hero.service';\nimport { Hero } from '../hero';\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$: Observable<Hero>;\n\n constructor(\n private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>,\n private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>,\n private service: HeroService\n ) {}\n\n ngOnInit() {\n this.hero$ = this.route.paramMap.pipe(\n switchMap((params: <a href=\"api/router/ParamMap\" class=\"code-anchor\">ParamMap</a>) =>\n this.service.getHero(params.get('id')))\n );\n }\n\n gotoHeroes(hero: Hero) {\n const heroId = hero ? hero.id : null;\n // Pass along the hero id if available\n // so that the HeroList component can select that hero.\n // Include a junk 'foo' property for fun.\n this.router.navigate(['/heroes', { id: heroId, foo: 'foo' }]);\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"hero.service.ts\" path=\"router/src/app/heroes/hero.service.ts\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\n\nimport { Observable, of } from 'rxjs';\nimport { map } from 'rxjs/operators';\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>({\n providedIn: 'root',\n})\nexport class HeroService {\n\n constructor(private messageService: MessageService) { }\n\n getHeroes(): Observable<Hero[]> {\n // TODO: send the message _after_ fetching the heroes\n this.messageService.add('HeroService: fetched heroes');\n return of(HEROES);\n }\n\n getHero(id: number | string) {\n return this.getHeroes().pipe(\n // (+) before `id` turns the string into a number\n map((heroes: Hero[]) => heroes.find(hero => hero.id === +id))\n );\n }\n}\n\n\n\n</code-pane>\n\n <code-pane header=\"heroes.module.ts\" path=\"router/src/app/heroes/heroes.module.ts\">\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';\nimport { <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a> } from '@angular/forms';\n\nimport { HeroListComponent } from './hero-list/hero-list.component';\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\n\nimport { HeroesRoutingModule } from './heroes-routing.module';\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 <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>,\n HeroesRoutingModule\n ],\n declarations: [\n HeroListComponent,\n HeroDetailComponent\n ]\n})\nexport class HeroesModule {}\n\n\n</code-pane>\n\n <code-pane header=\"heroes-routing.module.ts\" path=\"router/src/app/heroes/heroes-routing.module.2.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 { HeroListComponent } from './hero-list/hero-list.component';\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\n\nconst heroesRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'heroes', component: HeroListComponent, data: { <a href=\"api/animations/animation\" class=\"code-anchor\">animation</a>: 'heroes' } },\n { path: 'hero/:id', component: HeroDetailComponent, data: { <a href=\"api/animations/animation\" class=\"code-anchor\">animation</a>: 'hero' } }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(heroesRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class HeroesRoutingModule { }\n\n</code-pane>\n\n <code-pane header=\"message.service.ts\" path=\"router/src/app/message.service.ts\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class MessageService {\n messages: string[] = [];\n\n add(message: string) {\n this.messages.push(message);\n }\n\n clear() {\n this.messages = [];\n }\n}\n\n\n</code-pane>\n\n</code-tabs>\n<a id=\"milestone-4\"></a>\n<h2 id=\"milestone-4-crisis-center-feature\">Milestone 4: Crisis center feature<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#milestone-4-crisis-center-feature\"><i class=\"material-icons\">link</i></a></h2>\n<p>This section shows you how to add child routes and use relative routing in your app.</p>\n<p>To add more features to the app's current crisis center, take similar steps as for the heroes feature:</p>\n<ul>\n<li>Create a <code>crisis-center</code> subfolder in the <code>src/app</code> folder.</li>\n<li>Copy the files and folders from <code>app/heroes</code> into the new <code>crisis-center</code> folder.</li>\n<li>In the new files, change every mention of \"hero\" to \"crisis\", and \"heroes\" to \"crises\".</li>\n<li>Rename the NgModule files to <code>crisis-center.module.ts</code> and <code>crisis-center-routing.module.ts</code>.</li>\n</ul>\n<p>Use mock crises instead of mock heroes:</p>\n<code-example path=\"router/src/app/crisis-center/mock-crises.ts\" header=\"src/app/crisis-center/mock-crises.ts\">\nimport { Crisis } from './crisis';\n\nexport const CRISES: Crisis[] = [\n { id: 1, name: 'Dragon Burning Cities' },\n { id: 2, name: 'Sky Rains Great White Sharks' },\n { id: 3, name: 'Giant Asteroid Heading For Earth' },\n { id: 4, name: 'Procrastinators Meeting Delayed Again' },\n];\n\n\n</code-example>\n<p>The resulting crisis center is a foundation for introducing a new concept—child routing.\nYou can leave Heroes in its current state as a contrast with the Crisis Center.</p>\n<div class=\"alert is-helpful\">\n<p>In keeping with the <a href=\"https://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html\" title=\"Separation of Concerns\">Separation of Concerns principle</a>, changes to the Crisis Center don't affect the <code>AppModule</code> or any other feature's component.</p>\n</div>\n<a id=\"crisis-child-routes\"></a>\n<h3 id=\"a-crisis-center-with-child-routes\">A crisis center with child routes<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#a-crisis-center-with-child-routes\"><i class=\"material-icons\">link</i></a></h3>\n<p>This section shows you how to organize the crisis center to conform to the following recommended pattern for Angular applications:</p>\n<ul>\n<li>Each feature area resides in its own folder.</li>\n<li>Each feature has its own Angular feature module.</li>\n<li>Each area has its own area root component.</li>\n<li>Each area root component has its own router outlet and child routes.</li>\n<li>Feature area routes rarely (if ever) cross with routes of other features.</li>\n</ul>\n<p>If your app had many feature areas, the app component trees might look like this:</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/router/component-tree.png\" alt=\"Component Tree\" width=\"473\" height=\"258\">\n</div>\n<a id=\"child-routing-component\"></a>\n<h3 id=\"child-routing-component\">Child routing component<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#child-routing-component\"><i class=\"material-icons\">link</i></a></h3>\n<p>Generate a <code>CrisisCenter</code> component in the <code>crisis-center</code> folder:</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate component crisis-center/crisis-center\n</code-example>\n<p>Update the component template with the following markup:</p>\n<code-example path=\"router/src/app/crisis-center/crisis-center/crisis-center.component.html\" header=\"src/app/crisis-center/crisis-center/crisis-center.component.html\">\n<h2>CRISIS CENTER</h2>\n<<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n\n</code-example>\n<p>The <code>CrisisCenterComponent</code> has the following in common with the <code>AppComponent</code>:</p>\n<ul>\n<li>It is the root of the crisis center area, just as <code>AppComponent</code> is the root of the entire application.</li>\n<li>It is a shell for the crisis management feature area, just as the <code>AppComponent</code> is a shell to manage the high-level workflow.</li>\n</ul>\n<p>Like most shells, the <code>CrisisCenterComponent</code> class is minimal because it has no business logic, and its template has no links, just a title and <code><<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></code> for the crisis center child component.</p>\n<a id=\"child-route-config\"></a>\n<h3 id=\"child-route-configuration\">Child route configuration<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#child-route-configuration\"><i class=\"material-icons\">link</i></a></h3>\n<p>As a host page for the \"Crisis Center\" feature, generate a <code>CrisisCenterHome</code> component in the <code>crisis-center</code> folder.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate component crisis-center/crisis-center-home\n</code-example>\n<p>Update the template with a welcome message to the <code>Crisis Center</code>.</p>\n<code-example path=\"router/src/app/crisis-center/crisis-center-home/crisis-center-home.component.html\" header=\"src/app/crisis-center/crisis-center-home/crisis-center-home.component.html\">\n<p>Welcome to the Crisis Center</p>\n\n</code-example>\n<p>Update the <code>crisis-center-routing.module.ts</code> you renamed after copying it from <code>heroes-routing.module.ts</code> file.\nThis time, you define child routes within the parent <code>crisis-center</code> route.</p>\n<code-example path=\"router/src/app/crisis-center/crisis-center-routing.module.1.ts\" header=\"src/app/crisis-center/crisis-center-routing.module.ts (Routes)\" region=\"routes\">\nconst crisisCenterRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n {\n path: 'crisis-center',\n component: CrisisCenterComponent,\n children: [\n {\n path: '',\n component: CrisisListComponent,\n children: [\n {\n path: ':id',\n component: CrisisDetailComponent\n },\n {\n path: '',\n component: CrisisCenterHomeComponent\n }\n ]\n }\n ]\n }\n];\n\n</code-example>\n<p>Notice that the parent <code>crisis-center</code> route has a <code>children</code> property with a single route containing the <code>CrisisListComponent</code>.\nThe <code>CrisisListComponent</code> route also has a <code>children</code> array with two routes.</p>\n<p>These two routes navigate to the crisis center child components,\n<code>CrisisCenterHomeComponent</code> and <code>CrisisDetailComponent</code>, respectively.</p>\n<p>There are important differences in the way the router treats child routes.</p>\n<p>The router displays the components of these routes in the <code><a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a></code> of the <code>CrisisCenterComponent</code>, not in the <code><a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a></code> of the <code>AppComponent</code> shell.</p>\n<p>The <code>CrisisListComponent</code> contains the crisis list and a <code><a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a></code> to display the <code>Crisis Center Home</code> and <code>Crisis Detail</code> route components.</p>\n<p>The <code>Crisis Detail</code> route is a child of the <code>Crisis List</code>.\nThe router <a href=\"guide/router-tutorial-toh#reuse\">reuses components</a> by default, so the <code>Crisis Detail</code> component will be re-used as you select different crises.\nIn contrast, back in the <code>Hero Detail</code> route, <a href=\"guide/router-tutorial-toh#snapshot-the-no-observable-alternative\">the component was recreated</a> each time you selected a different hero from the list of heroes.</p>\n<p>At the top level, paths that begin with <code>/</code> refer to the root of the application.\nBut child routes extend the path of the parent route.\nWith each step down the route tree,\nyou add a slash followed by the route path, unless the path is empty.</p>\n<p>Apply that logic to navigation within the crisis center for which the parent path is <code>/crisis-center</code>.</p>\n<ul>\n<li>\n<p>To navigate to the <code>CrisisCenterHomeComponent</code>, the full URL is <code>/crisis-center</code> (<code>/crisis-center</code> + <code>''</code> + <code>''</code>).</p>\n</li>\n<li>\n<p>To navigate to the <code>CrisisDetailComponent</code> for a crisis with <code>id=2</code>, the full URL is\n<code>/crisis-center/2</code> (<code>/crisis-center</code> + <code>''</code> + <code>'/2'</code>).</p>\n</li>\n</ul>\n<p>The absolute URL for the latter example, including the <code>localhost</code> origin, is as follows:</p>\n<code-example>\n localhost:4200/crisis-center/2\n\n</code-example>\n<p>Here's the complete <code>crisis-center-routing.module.ts</code> file with its imports.</p>\n<code-example path=\"router/src/app/crisis-center/crisis-center-routing.module.1.ts\" header=\"src/app/crisis-center/crisis-center-routing.module.ts (excerpt)\">\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 { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component';\nimport { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { CrisisCenterComponent } from './crisis-center/crisis-center.component';\nimport { CrisisDetailComponent } from './crisis-detail/crisis-detail.component';\n\nconst crisisCenterRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n {\n path: 'crisis-center',\n component: CrisisCenterComponent,\n children: [\n {\n path: '',\n component: CrisisListComponent,\n children: [\n {\n path: ':id',\n component: CrisisDetailComponent\n },\n {\n path: '',\n component: CrisisCenterHomeComponent\n }\n ]\n }\n ]\n }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(crisisCenterRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class CrisisCenterRoutingModule { }\n\n</code-example>\n<a id=\"import-crisis-module\"></a>\n<h3 id=\"import-crisis-center-module-into-the-appmodule-routes\">Import crisis center module into the <code>AppModule</code> routes<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#import-crisis-center-module-into-the-appmodule-routes\"><i class=\"material-icons\">link</i></a></h3>\n<p>As with the <code>HeroesModule</code>, you must add the <code>CrisisCenterModule</code> to the <code>imports</code> array of the <code>AppModule</code>\n<em>before</em> the <code>AppRoutingModule</code>:</p>\n<code-tabs>\n\n <code-pane path=\"router/src/app/crisis-center/crisis-center.module.ts\" header=\"src/app/crisis-center/crisis-center.module.ts\">\nimport { <a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a> } from '@angular/core';\nimport { <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a> } from '@angular/forms';\nimport { <a href=\"api/common/CommonModule\" class=\"code-anchor\">CommonModule</a> } from '@angular/common';\n\nimport { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component';\nimport { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { CrisisCenterComponent } from './crisis-center/crisis-center.component';\nimport { CrisisDetailComponent } from './crisis-detail/crisis-detail.component';\n\nimport { CrisisCenterRoutingModule } from './crisis-center-routing.module';\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 <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>,\n CrisisCenterRoutingModule\n ],\n declarations: [\n CrisisCenterComponent,\n CrisisListComponent,\n CrisisCenterHomeComponent,\n CrisisDetailComponent\n ]\n})\nexport class CrisisCenterModule {}\n\n\n</code-pane>\n\n <code-pane path=\"router/src/app/app.module.4.ts\" header=\"src/app/app.module.ts (import CrisisCenterModule)\" region=\"crisis-center-module\">\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';\nimport { <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a> } from '@angular/forms';\n\nimport { AppComponent } from './app.component';\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\nimport { ComposeMessageComponent } from './compose-message/compose-message.component';\n\nimport { AppRoutingModule } from './app-routing.module';\nimport { HeroesModule } from './heroes/heroes.module';\nimport { CrisisCenterModule } from './crisis-center/crisis-center.module';\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 <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>,\n HeroesModule,\n CrisisCenterModule,\n AppRoutingModule\n ],\n declarations: [\n AppComponent,\n PageNotFoundComponent\n ],\n bootstrap: [ AppComponent ]\n})\nexport class AppModule { }\n\n</code-pane>\n\n</code-tabs>\n<p>Remove the initial crisis center route from the <code>app-routing.module.ts</code> because now the <code>HeroesModule</code> and the <code>CrisisCenter</code> modules provide the feature routes.</p>\n<p>The <code>app-routing.module.ts</code> file retains the top-level application routes such as the default and wildcard routes.</p>\n<code-example path=\"router/src/app/app-routing.module.3.ts\" header=\"src/app/app-routing.module.ts (v3)\" region=\"v3\">\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 { PageNotFoundComponent } from './page-not-found/page-not-found.component';\n\nconst appRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: '', redirectTo: '/heroes', pathMatch: 'full' },\n { path: '**', component: PageNotFoundComponent }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forRoot(\n appRoutes,\n { enableTracing: true } // <-- debugging purposes only\n )\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class AppRoutingModule {}\n\n\n</code-example>\n<a id=\"relative-navigation\"></a>\n<h3 id=\"relative-navigation\">Relative navigation<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#relative-navigation\"><i class=\"material-icons\">link</i></a></h3>\n<p>While building out the crisis center feature, you navigated to the\ncrisis detail route using an absolute path that begins with a slash.</p>\n<p>The router matches such absolute paths to routes starting from the top of the route configuration.</p>\n<p>You could continue to use absolute paths like this to navigate inside the Crisis Center feature, but that pins the links to the parent routing structure.\nIf you changed the parent <code>/crisis-center</code> path, you would have to change the link parameters array.</p>\n<p>You can free the links from this dependency by defining paths that are relative to the current URL segment.\nNavigation within the feature area remains intact even if you change the parent route path to the feature.</p>\n<div class=\"alert is-helpful\">\n<p>The router supports directory-like syntax in a <em>link parameters list</em> to help guide route name lookup:</p>\n<p><code>./</code> or <code>no leading slash</code> is relative to the current level.</p>\n<p><code>../</code> to go up one level in the route path.</p>\n<p>You can combine relative navigation syntax with an ancestor path.\nIf you must navigate to a sibling route, you could use the <code>../<sibling></code> convention to go up\none level, then over and down the sibling route path.</p>\n</div>\n<p>To navigate a relative path with the <code>Router.navigate</code> method, you must supply the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code>\nto give the router knowledge of where you are in the current route tree.</p>\n<p>After the <em>link parameters array</em>, add an object with a <code>relativeTo</code> property set to the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code>.\nThe router then calculates the target URL based on the active route's location.</p>\n<div class=\"alert is-helpful\">\n<p>Always specify the complete absolute path when calling router's <code>navigateByUrl()</code> method.</p>\n</div>\n<a id=\"nav-to-crisis\"></a>\n<h3 id=\"navigate-to-crisis-list-with-a-relative-url\">Navigate to crisis list with a relative URL<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#navigate-to-crisis-list-with-a-relative-url\"><i class=\"material-icons\">link</i></a></h3>\n<p>You've already injected the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> that you need to compose the relative navigation path.</p>\n<p>When using a <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> to navigate instead of the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> service, you'd use the same link parameters array, but you wouldn't provide the object with the <code>relativeTo</code> property.\nThe <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> is implicit in a <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> directive.</p>\n<p>Update the <code>gotoCrises()</code> method of the <code>CrisisDetailComponent</code> to navigate back to the Crisis Center list using relative path navigation.</p>\n<code-example path=\"router/src/app/crisis-center/crisis-detail/crisis-detail.component.ts\" header=\"src/app/crisis-center/crisis-detail/crisis-detail.component.ts (relative navigation)\" region=\"gotoCrises-navigate\">\n// Relative navigation back to the crises\nthis.router.navigate(['../', { id: crisisId, foo: 'foo' }], { relativeTo: this.route });\n\n</code-example>\n<p>Notice that the path goes up a level using the <code>../</code> syntax.\nIf the current crisis <code>id</code> is <code>3</code>, the resulting path back to the crisis list is <code>/crisis-center/;id=3;foo=foo</code>.</p>\n<a id=\"named-outlets\"></a>\n<h3 id=\"displaying-multiple-routes-in-named-outlets\">Displaying multiple routes in named outlets<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#displaying-multiple-routes-in-named-outlets\"><i class=\"material-icons\">link</i></a></h3>\n<p>You decide to give users a way to contact the crisis center.\nWhen a user clicks a \"Contact\" button, you want to display a message in a popup view.</p>\n<p>The popup should stay open, even when switching between pages in the application, until the user closes it\nby sending the message or canceling.\nClearly you can't put the popup in the same outlet as the other pages.</p>\n<p>Until now, you've defined a single outlet and you've nested child routes under that outlet to group routes together.\nThe router only supports one primary unnamed outlet per template.</p>\n<p>A template can also have any number of named outlets.\nEach named outlet has its own set of routes with their own components.\nMultiple outlets can display different content, determined by different routes, all at the same time.</p>\n<p>Add an outlet named \"popup\" in the <code>AppComponent</code>, directly below the unnamed outlet.</p>\n<code-example path=\"router/src/app/app.component.4.html\" header=\"src/app/app.component.html (outlets)\" region=\"outlets\">\n<div [@routeAnimation]=\"getAnimationData(routerOutlet)\">\n <<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a> #routerOutlet=\"outlet\"></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n</div>\n<<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a> name=\"popup\"></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n\n</code-example>\n<p>That's where a popup will go, once you learn how to route a popup component to it.</p>\n<a id=\"secondary-routes\"></a>\n<h4 id=\"secondary-routes\">Secondary routes<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#secondary-routes\"><i class=\"material-icons\">link</i></a></h4>\n<p>Named outlets are the targets of <em>secondary routes</em>.</p>\n<p>Secondary routes look like primary routes and you configure them the same way.\nThey differ in a few key respects.</p>\n<ul>\n<li>They are independent of each other.</li>\n<li>They work in combination with other routes.</li>\n<li>They are displayed in named outlets.</li>\n</ul>\n<p>Generate a new component to compose the message.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate component compose-message\n</code-example>\n<p>It displays a short form with a header, an input box for the message,\nand two buttons, \"Send\" and \"Cancel\".</p>\n<div class=\"lightbox\">\n <img src=\"generated/images/guide/router/contact-popup.png\" alt=\"Contact popup\" width=\"250\" height=\"262\">\n</div>\n<p>Here's the component, its template and styles:</p>\n<code-tabs>\n\n <code-pane header=\"src/app/compose-message/compose-message.component.css\" path=\"router/src/app/compose-message/compose-message.component.css\">\n:host {\n position: relative; bottom: 10%;\n}\n\n</code-pane>\n\n <code-pane header=\"src/app/compose-message/compose-message.component.html\" path=\"router/src/app/compose-message/compose-message.component.html\">\n<h3>Contact Crisis Center</h3>\n<div *<a href=\"api/common/NgIf\" class=\"code-anchor\">ngIf</a>=\"details\">\n {{ details }}\n</div>\n<div>\n <div>\n <label>Message: </label>\n </div>\n <div>\n <<a href=\"api/forms/DefaultValueAccessor\" class=\"code-anchor\">textarea</a> [(<a href=\"api/forms/NgModel\" class=\"code-anchor\">ngModel</a>)]=\"message\" rows=\"10\" cols=\"35\" [disabled]=\"sending\"></<a href=\"api/forms/DefaultValueAccessor\" class=\"code-anchor\">textarea</a>>\n </div>\n</div>\n<p *<a href=\"api/common/NgIf\" class=\"code-anchor\">ngIf</a>=\"!sending\">\n <button (click)=\"send()\">Send</button>\n <button (click)=\"cancel()\">Cancel</button>\n</p>\n\n\n</code-pane>\n\n <code-pane header=\"src/app/compose-message/compose-message.component.ts\" path=\"router/src/app/compose-message/compose-message.component.ts\">\nimport { <a href=\"api/core/Component\" class=\"code-anchor\">Component</a>, <a href=\"api/core/HostBinding\" class=\"code-anchor\">HostBinding</a> } from '@angular/core';\nimport { <a href=\"api/router/Router\" class=\"code-anchor\">Router</a> } from '@angular/router';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-compose-message',\n templateUrl: './compose-message.component.html',\n styleUrls: ['./compose-message.component.css']\n})\nexport class ComposeMessageComponent {\n details: string;\n message: string;\n sending = false;\n\n constructor(private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) {}\n\n send() {\n this.sending = true;\n this.details = 'Sending Message...';\n\n setTimeout(() => {\n this.sending = false;\n this.closePopup();\n }, 1000);\n }\n\n cancel() {\n this.closePopup();\n }\n\n closePopup() {\n // Providing a `null` value to the named outlet\n // clears the contents of the named outlet\n this.router.navigate([{ outlets: { popup: null }}]);\n }\n}\n\n\n</code-pane>\n\n</code-tabs>\n<p>It looks similar to any other component in this guide, but there are two key differences.</p>\n<p>Note that the <code>send()</code> method simulates latency by waiting a second before \"sending\" the message and closing the popup.</p>\n<p>The <code>closePopup()</code> method closes the popup view by navigating to the popup outlet with a <code>null</code> which the section on <a href=\"guide/router-tutorial-toh#clear-secondary-routes\">clearing secondary routes</a> covers.</p>\n<a id=\"add-secondary-route\"></a>\n<h4 id=\"add-a-secondary-route\">Add a secondary route<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#add-a-secondary-route\"><i class=\"material-icons\">link</i></a></h4>\n<p>Open the <code>AppRoutingModule</code> and add a new <code>compose</code> route to the <code>appRoutes</code>.</p>\n<code-example path=\"router/src/app/app-routing.module.3.ts\" header=\"src/app/app-routing.module.ts (compose route)\" region=\"compose\">\n{\n path: 'compose',\n component: ComposeMessageComponent,\n outlet: 'popup'\n},\n\n</code-example>\n<p>In addition to the <code>path</code> and <code>component</code> properties, there's a new property called <code>outlet</code>, which is set to <code>'popup'</code>.\nThis route now targets the popup outlet and the <code>ComposeMessageComponent</code> will display there.</p>\n<p>To give users a way to open the popup, add a \"Contact\" link to the <code>AppComponent</code> template.</p>\n<code-example path=\"router/src/app/app.component.4.html\" header=\"src/app/app.component.html (contact-link)\" region=\"contact-link\">\n<a [<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]=\"[{ outlets: { popup: ['compose'] } }]\">Contact</a>\n\n</code-example>\n<p>Although the <code>compose</code> route is configured to the \"popup\" outlet, that's not sufficient for connecting the route to a <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> directive.\nYou have to specify the named outlet in a <em>link parameters array</em> and bind it to the <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> with a property binding.</p>\n<p>The <em>link parameters array</em> contains an object with a single <code>outlets</code> property whose value is another object keyed by one (or more) outlet names.\nIn this case there is only the \"popup\" outlet property and its value is another <em>link parameters array</em> that specifies the <code>compose</code> route.</p>\n<p>In other words, when the user clicks this link, the router displays the component associated with the <code>compose</code> route in the <code>popup</code> outlet.</p>\n<div class=\"alert is-helpful\">\n<p>This <code>outlets</code> object within an outer object was unnecessary when there was only one route and one unnamed outlet.</p>\n<p>The router assumed that your route specification targeted the unnamed primary outlet and created these objects for you.</p>\n<p>Routing to a named outlet has revealed a router feature:\nyou can target multiple outlets with multiple routes in the same <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> directive.</p>\n</div>\n<a id=\"secondary-route-navigation\"></a>\n<h4 id=\"secondary-route-navigation-merging-routes-during-navigation\">Secondary route navigation: merging routes during navigation<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#secondary-route-navigation-merging-routes-during-navigation\"><i class=\"material-icons\">link</i></a></h4>\n<p>Navigate to the <em>Crisis Center</em> and click \"Contact\".\nyou should see something like the following URL in the browser address bar.</p>\n<code-example>\n http://.../crisis-center(popup:compose)\n\n</code-example>\n<p>The relevant part of the URL follows the <code>...</code>:</p>\n<ul>\n<li>The <code>crisis-center</code> is the primary navigation.</li>\n<li>Parentheses surround the secondary route.</li>\n<li>The secondary route consists of an outlet name (<code>popup</code>), a <code>colon</code> separator, and the secondary route path (<code>compose</code>).</li>\n</ul>\n<p>Click the <em>Heroes</em> link and look at the URL again.</p>\n<code-example>\n http://.../heroes(popup:compose)\n</code-example>\n<p>The primary navigation part has changed; the secondary route is the same.</p>\n<p>The router is keeping track of two separate branches in a navigation tree and generating a representation of that tree in the URL.</p>\n<p>You can add many more outlets and routes, at the top level and in nested levels, creating a navigation tree with many branches and the router will generate the URLs to go with it.</p>\n<p>You can tell the router to navigate an entire tree at once by filling out the <code>outlets</code> object and then pass that object inside a <em>link parameters array</em> to the <code>router.navigate</code> method.</p>\n<a id=\"clear-secondary-routes\"></a>\n<h4 id=\"clearing-secondary-routes\">Clearing secondary routes<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#clearing-secondary-routes\"><i class=\"material-icons\">link</i></a></h4>\n<p>Like regular outlets, secondary outlets persists until you navigate away to a new component.</p>\n<p>Each secondary outlet has its own navigation, independent of the navigation driving the primary outlet.\nChanging a current route that displays in the primary outlet has no effect on the popup outlet.\nThat's why the popup stays visible as you navigate among the crises and heroes.</p>\n<p>The <code>closePopup()</code> method again:</p>\n<code-example path=\"router/src/app/compose-message/compose-message.component.ts\" header=\"src/app/compose-message/compose-message.component.ts (closePopup)\" region=\"closePopup\">\nclosePopup() {\n // Providing a `null` value to the named outlet\n // clears the contents of the named outlet\n this.router.navigate([{ outlets: { popup: null }}]);\n}\n\n</code-example>\n<p>Clicking the \"send\" or \"cancel\" buttons clears the popup view.\nThe <code>closePopup()</code> function navigates imperatively with the <code><a href=\"api/router/Router#navigate\" class=\"code-anchor\">Router.navigate()</a></code> method, passing in a <a href=\"guide/router-tutorial-toh#link-parameters-array\">link parameters array</a>.</p>\n<p>Like the array bound to the <em>Contact</em> <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> in the <code>AppComponent</code>, this one includes an object with an <code>outlets</code> property.\nThe <code>outlets</code> property value is another object with outlet names for keys.\nThe only named outlet is <code>'popup'</code>.</p>\n<p>This time, the value of <code>'popup'</code> is <code>null</code>.\nThat's not a route, but it is a legitimate value.\nSetting the popup <code><a href=\"api/router/RouterOutlet\" class=\"code-anchor\">RouterOutlet</a></code> to <code>null</code> clears the outlet and removes the secondary popup route from the current URL.</p>\n<a id=\"guards\"></a>\n<a id=\"milestone-5-route-guards\"></a>\n<h2 id=\"milestone-5-route-guards\">Milestone 5: Route guards<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#milestone-5-route-guards\"><i class=\"material-icons\">link</i></a></h2>\n<p>At the moment, any user can navigate anywhere in the application anytime, but sometimes you need to control access to different parts of your app for various reasons. Some of which may include the following:</p>\n<ul>\n<li>Perhaps the user is not authorized to navigate to the target component.</li>\n<li>Maybe the user must login (authenticate) first.</li>\n<li>Maybe you should fetch some data before you display the target component.</li>\n<li>You might want to save pending changes before leaving a component.</li>\n<li>You might ask the user if it's OK to discard pending changes rather than save them.</li>\n</ul>\n<p>You add guards to the route configuration to handle these scenarios.</p>\n<p>A guard's return value controls the router's behavior:</p>\n<ul>\n<li>If it returns <code>true</code>, the navigation process continues.</li>\n<li>If it returns <code>false</code>, the navigation process stops and the user stays put.</li>\n<li>If it returns a <code><a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a></code>, the current navigation cancels and a new navigation is initiated to the <code><a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a></code> returned.</li>\n</ul>\n<div class=\"alert is-helpful\">\n<p><strong>Note:</strong> The guard can also tell the router to navigate elsewhere, effectively canceling the current navigation.\nWhen doing so inside a guard, the guard should return <code>false</code>;</p>\n</div>\n<p>The guard might return its boolean answer synchronously.\nBut in many cases, the guard can't produce an answer synchronously.\nThe guard could ask the user a question, save changes to the server, or fetch fresh data.\nThese are all asynchronous operations.</p>\n<p>Accordingly, a routing guard can return an <code>Observable<boolean></code> or a <code>Promise<boolean></code> and the\nrouter will wait for the observable to resolve to <code>true</code> or <code>false</code>.</p>\n<div class=\"alert is-critical\">\n<p><strong>Note:</strong> The observable provided to the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> must also complete. If the observable does not complete, the navigation does not continue.</p>\n</div>\n<p>The router supports multiple guard interfaces:</p>\n<ul>\n<li>\n<p><a href=\"api/router/CanActivate\"><code>CanActivate</code></a> to mediate navigation <em>to</em> a route.</p>\n</li>\n<li>\n<p><a href=\"api/router/CanActivateChild\"><code>CanActivateChild</code></a> to mediate navigation <em>to</em> a child route.</p>\n</li>\n<li>\n<p><a href=\"api/router/CanDeactivate\"><code>CanDeactivate</code></a> to mediate navigation <em>away</em> from the current route.</p>\n</li>\n<li>\n<p><a href=\"api/router/Resolve\"><code>Resolve</code></a> to perform route data retrieval <em>before</em> route activation.</p>\n</li>\n<li>\n<p><a href=\"api/router/CanLoad\"><code>CanLoad</code></a> to mediate navigation <em>to</em> a feature module loaded <em>asynchronously</em>.</p>\n</li>\n</ul>\n<p>You can have multiple guards at every level of a routing hierarchy.\nThe router checks the <code><a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a></code> and <code><a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a></code> guards first, from the deepest child route to the top.\nThen it checks the <code><a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a></code> guards from the top down to the deepest child route.\nIf the feature module is loaded asynchronously, the <code><a href=\"api/router/CanLoad\" class=\"code-anchor\">CanLoad</a></code> guard is checked before the module is loaded.\nIf <em>any</em> guard returns false, pending guards that have not completed will be canceled, and the entire navigation is canceled.</p>\n<p>There are several examples over the next few sections.</p>\n<a id=\"can-activate-guard\"></a>\n<h3 id=\"canactivate-requiring-authentication\"><code><a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a></code>: requiring authentication<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#canactivate-requiring-authentication\"><i class=\"material-icons\">link</i></a></h3>\n<p>Applications often restrict access to a feature area based on who the user is.\nYou could permit access only to authenticated users or to users with a specific role.\nYou might block or limit access until the user's account is activated.</p>\n<p>The <code><a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a></code> guard is the tool to manage these navigation business rules.</p>\n<h4 id=\"add-an-admin-feature-module\">Add an admin feature module<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#add-an-admin-feature-module\"><i class=\"material-icons\">link</i></a></h4>\n<p>This section guides you through extending the crisis center with some new administrative features.\nStart by adding a new feature module named <code>AdminModule</code>.</p>\n<p>Generate an <code>admin</code> folder with a feature module file and a routing configuration file.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate module admin --routing\n</code-example>\n<p>Next, generate the supporting components.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate component admin/admin-dashboard\n</code-example>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate component admin/admin\n</code-example>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate component admin/manage-crises\n</code-example>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate component admin/manage-heroes\n</code-example>\n<p>The admin feature file structure looks like this:</p>\n<div class=\"filetree\">\n <div class=\"file\">\n src/app/admin\n </div>\n <div class=\"children\">\n <div class=\"file\">\n admin\n </div>\n <div class=\"children\">\n <div class=\"file\">\n admin.component.css\n </div>\n <div class=\"file\">\n admin.component.html\n </div>\n <div class=\"file\">\n admin.component.ts\n </div>\n </div>\n <div class=\"file\">\n admin-dashboard\n </div>\n <div class=\"children\">\n <div class=\"file\">\n admin-dashboard.component.css\n </div>\n <div class=\"file\">\n admin-dashboard.component.html\n </div>\n <div class=\"file\">\n admin-dashboard.component.ts\n </div>\n </div>\n <div class=\"file\">\n manage-crises\n </div>\n <div class=\"children\">\n <div class=\"file\">\n manage-crises.component.css\n </div>\n <div class=\"file\">\n manage-crises.component.html\n </div>\n <div class=\"file\">\n manage-crises.component.ts\n </div>\n </div>\n <div class=\"file\">\n manage-heroes\n </div>\n <div class=\"children\">\n <div class=\"file\">\n manage-heroes.component.css\n </div>\n <div class=\"file\">\n manage-heroes.component.html\n </div>\n <div class=\"file\">\n manage-heroes.component.ts\n </div>\n </div>\n <div class=\"file\">\n admin.module.ts\n </div>\n <div class=\"file\">\n admin-routing.module.ts\n </div>\n </div>\n</div>\n<p>The admin feature module contains the <code>AdminComponent</code> used for routing within the\nfeature module, a dashboard route and two unfinished components to manage crises and heroes.</p>\n<code-tabs>\n\n <code-pane header=\"src/app/admin/admin/admin.component.html\" path=\"router/src/app/admin/admin/admin.component.html\">\n<h3>ADMIN</h3>\n<nav>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"./\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\"\n [routerLinkActiveOptions]=\"{ exact: true }\">Dashboard</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"./crises\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Manage Crises</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"./heroes\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Manage Heroes</a>\n</nav>\n<<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n\n</code-pane>\n\n <code-pane header=\"src/app/admin/admin-dashboard/admin-dashboard.component.html\" path=\"router/src/app/admin/admin-dashboard/admin-dashboard.component.1.html\">\n<p>Dashboard</p>\n\n</code-pane>\n\n <code-pane header=\"src/app/admin/admin.module.ts\" path=\"router/src/app/admin/admin.module.ts\">\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\nimport { AdminComponent } from './admin/admin.component';\nimport { AdminDashboardComponent } from './admin-dashboard/admin-dashboard.component';\nimport { ManageCrisesComponent } from './manage-crises/manage-crises.component';\nimport { ManageHeroesComponent } from './manage-heroes/manage-heroes.component';\n\nimport { AdminRoutingModule } from './admin-routing.module';\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 AdminRoutingModule\n ],\n declarations: [\n AdminComponent,\n AdminDashboardComponent,\n ManageCrisesComponent,\n ManageHeroesComponent\n ]\n})\nexport class AdminModule {}\n\n\n</code-pane>\n\n <code-pane header=\"src/app/admin/manage-crises/manage-crises.component.html\" path=\"router/src/app/admin/manage-crises/manage-crises.component.html\">\n<p>Manage your crises here</p>\n\n</code-pane>\n\n <code-pane header=\"src/app/admin/manage-heroes/manage-heroes.component.html\" path=\"router/src/app/admin/manage-heroes/manage-heroes.component.html\">\n<p>Manage your heroes here</p>\n\n</code-pane>\n\n</code-tabs>\n<div class=\"alert is-helpful\">\n<p>Although the admin dashboard <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> only contains a relative slash without an additional URL segment, it is a match to any route within the admin feature area.\nYou only want the <code>Dashboard</code> link to be active when the user visits that route.\nAdding an additional binding to the <code>Dashboard</code> routerLink,<code>[routerLinkActiveOptions]=\"{ exact: true }\"</code>, marks the <code>./</code> link as active when the user navigates to the <code>/admin</code> URL and not when navigating to any of the child routes.</p>\n</div>\n<a id=\"component-less-route\"></a>\n<h5 id=\"component-less-route-grouping-routes-without-a-component\">Component-less route: grouping routes without a component<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#component-less-route-grouping-routes-without-a-component\"><i class=\"material-icons\">link</i></a></h5>\n<p>The initial admin routing configuration:</p>\n<code-example path=\"router/src/app/admin/admin-routing.module.1.ts\" header=\"src/app/admin/admin-routing.module.ts (admin routing)\" region=\"admin-routes\">\nconst adminRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n {\n path: 'admin',\n component: AdminComponent,\n children: [\n {\n path: '',\n children: [\n { path: 'crises', component: ManageCrisesComponent },\n { path: 'heroes', component: ManageHeroesComponent },\n { path: '', component: AdminDashboardComponent }\n ]\n }\n ]\n }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(adminRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class AdminRoutingModule {}\n\n</code-example>\n<p>The child route under the <code>AdminComponent</code> has a <code>path</code> and a <code>children</code> property but it's not using a <code>component</code>.\nThis defines a <em>component-less</em> route.</p>\n<p>To group the <code>Crisis Center</code> management routes under the <code>admin</code> path a component is unnecessary.\nAdditionally, a <em>component-less</em> route makes it easier to <a href=\"guide/router-tutorial-toh#can-activate-child-guard\">guard child routes</a>.</p>\n<p>Next, import the <code>AdminModule</code> into <code>app.module.ts</code> and add it to the <code>imports</code> array\nto register the admin routes.</p>\n<code-example path=\"router/src/app/app.module.4.ts\" header=\"src/app/app.module.ts (admin module)\" region=\"admin-module\">\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';\nimport { <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a> } from '@angular/forms';\n\nimport { AppComponent } from './app.component';\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\nimport { ComposeMessageComponent } from './compose-message/compose-message.component';\n\nimport { AppRoutingModule } from './app-routing.module';\nimport { HeroesModule } from './heroes/heroes.module';\nimport { CrisisCenterModule } from './crisis-center/crisis-center.module';\n\nimport { AdminModule } from './admin/admin.module';\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 <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>,\n HeroesModule,\n CrisisCenterModule,\n AdminModule,\n AppRoutingModule\n ],\n declarations: [\n AppComponent,\n ComposeMessageComponent,\n PageNotFoundComponent\n ],\n bootstrap: [ AppComponent ]\n})\nexport class AppModule { }\n\n\n</code-example>\n<p>Add an \"Admin\" link to the <code>AppComponent</code> shell so that users can get to this feature.</p>\n<code-example path=\"router/src/app/app.component.5.html\" header=\"src/app/app.component.html (template)\">\n<h1 class=\"title\">Angular <a href=\"api/router/Router\" class=\"code-anchor\">Router</a></h1>\n<nav>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/crisis-center\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Crisis Center</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/heroes\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Heroes</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/admin\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Admin</a>\n <a [<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]=\"[{ outlets: { popup: ['compose'] } }]\">Contact</a>\n</nav>\n<div [@routeAnimation]=\"getAnimationData(routerOutlet)\">\n <<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a> #routerOutlet=\"outlet\"></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n</div>\n<<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a> name=\"popup\"></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n\n</code-example>\n<a id=\"guard-admin-feature\"></a>\n<h4 id=\"guard-the-admin-feature\">Guard the admin feature<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#guard-the-admin-feature\"><i class=\"material-icons\">link</i></a></h4>\n<p>Currently, every route within the Crisis Center is open to everyone.\nThe new admin feature should be accessible only to authenticated users.</p>\n<p>Write a <code>canActivate()</code> guard method to redirect anonymous users to the\nlogin page when they try to enter the admin area.</p>\n<p>Generate an <code>AuthGuard</code> in the <code>auth</code> folder.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate guard auth/auth\n</code-example>\n<p>To demonstrate the fundamentals, this example only logs to the console, <code>returns</code> true immediately, and allows navigation to proceed:</p>\n<code-example path=\"router/src/app/auth/auth.guard.1.ts\" header=\"src/app/auth/auth.guard.ts (excerpt)\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport { <a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a>, <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>, <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a> } from '@angular/router';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class AuthGuard implements <a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a> {\n canActivate(\n next: <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>,\n <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>): boolean {\n console.log('AuthGuard#canActivate called');\n return true;\n }\n}\n\n\n</code-example>\n<p>Next, open <code>admin-routing.module.ts</code>, import the <code>AuthGuard</code> class, and\nupdate the admin route with a <code>canActivate</code> guard property that references it:</p>\n<code-example path=\"router/src/app/admin/admin-routing.module.2.ts\" header=\"src/app/admin/admin-routing.module.ts (guarded admin route)\" region=\"admin-route\">\nimport { AuthGuard } from '../auth/auth.guard';\n\nconst adminRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n {\n path: 'admin',\n component: AdminComponent,\n canActivate: [AuthGuard],\n children: [\n {\n path: '',\n children: [\n { path: 'crises', component: ManageCrisesComponent },\n { path: 'heroes', component: ManageHeroesComponent },\n { path: '', component: AdminDashboardComponent }\n ],\n }\n ]\n }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(adminRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class AdminRoutingModule {}\n\n</code-example>\n<p>The admin feature is now protected by the guard, but the guard requires more customization to work fully.</p>\n<a id=\"teach-auth\"></a>\n<h4 id=\"authenticate-with-authguard\">Authenticate with <code>AuthGuard</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#authenticate-with-authguard\"><i class=\"material-icons\">link</i></a></h4>\n<p>Make the <code>AuthGuard</code> mimic authentication.</p>\n<p>The <code>AuthGuard</code> should call an application service that can login a user and retain information about the current user. Generate a new <code>AuthService</code> in the <code>auth</code> folder:</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate service auth/auth\n</code-example>\n<p>Update the <code>AuthService</code> to log in the user:</p>\n<code-example path=\"router/src/app/auth/auth.service.ts\" header=\"src/app/auth/auth.service.ts (excerpt)\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\n\nimport { Observable, of } from 'rxjs';\nimport { tap, delay } from 'rxjs/operators';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class AuthService {\n isLoggedIn = false;\n\n // store the URL so we can redirect after logging in\n redirectUrl: string;\n\n login(): Observable<boolean> {\n return of(true).pipe(\n delay(1000),\n tap(val => this.isLoggedIn = true)\n );\n }\n\n logout(): void {\n this.isLoggedIn = false;\n }\n}\n\n\n</code-example>\n<p>Although it doesn't actually log in, it has an <code>isLoggedIn</code> flag to tell you whether the user is authenticated.\nIts <code>login()</code> method simulates an API call to an external service by returning an observable that resolves successfully after a short pause.\nThe <code>redirectUrl</code> property stores the URL that the user wanted to access so you can navigate to it after authentication.</p>\n<div class=\"alert is-helpful\">\n<p>To keep things minimal, this example redirects unauthenticated users to <code>/admin</code>.</p>\n</div>\n<p>Revise the <code>AuthGuard</code> to call the <code>AuthService</code>.</p>\n<code-example path=\"router/src/app/auth/auth.guard.2.ts\" header=\"src/app/auth/auth.guard.ts (v2)\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport { <a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a>, <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>, <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>, <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>, <a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a> } from '@angular/router';\n\nimport { AuthService } from './auth.service';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class AuthGuard implements <a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a> {\n constructor(private authService: AuthService, private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) {}\n\n canActivate(\n next: <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>,\n <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>): true|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a> {\n const url: string = state.url;\n\n return this.checkLogin(url);\n }\n\n checkLogin(url: string): true|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a> {\n if (this.authService.isLoggedIn) { return true; }\n\n // Store the attempted URL for redirecting\n this.authService.redirectUrl = url;\n\n // Redirect to the login page\n return this.router.parseUrl('/login');\n }\n}\n\n</code-example>\n<p>Notice that you inject the <code>AuthService</code> and the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> in the constructor.\nYou haven't provided the <code>AuthService</code> yet but it's good to know that you can inject helpful services into routing guards.</p>\n<p>This guard returns a synchronous boolean result.\nIf the user is logged in, it returns true and the navigation continues.</p>\n<p>The <code><a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a></code> contains the <em>future</em> route that will be activated and the <code><a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a></code> contains the <em>future</em> <code><a href=\"api/router/RouterState\" class=\"code-anchor\">RouterState</a></code> of the application, should you pass through the guard check.</p>\n<p>If the user is not logged in, you store the attempted URL the user came from using the <code><a href=\"api/router/RouterStateSnapshot#url\" class=\"code-anchor\">RouterStateSnapshot.url</a></code> and tell the router to redirect to a login page—a page you haven't created yet.\nReturning a <code><a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a></code> tells the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> to cancel the current navigation and schedule a new one to redirect the user.</p>\n<a id=\"add-login-component\"></a>\n<h4 id=\"add-the-logincomponent\">Add the <code>LoginComponent</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#add-the-logincomponent\"><i class=\"material-icons\">link</i></a></h4>\n<p>You need a <code>LoginComponent</code> for the user to log in to the app. After logging in, you'll redirect to the stored URL if available, or use the default URL.\nThere is nothing new about this component or the way you use it in the router configuration.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate component auth/login\n</code-example>\n<p>Register a <code>/login</code> route in the <code>auth/auth-routing.module.ts</code>.\nIn <code>app.module.ts</code>, import and add the <code>AuthModule</code> to the <code>AppModule</code> imports.</p>\n<code-tabs>\n\n <code-pane header=\"src/app/app.module.ts\" path=\"router/src/app/app.module.ts\" region=\"auth\">\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';\nimport { <a href=\"api/platform-browser/animations/BrowserAnimationsModule\" class=\"code-anchor\">BrowserAnimationsModule</a> } from '@angular/platform-browser/animations';\n\nimport { AppComponent } from './app.component';\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\nimport { ComposeMessageComponent } from './compose-message/compose-message.component';\n\nimport { AppRoutingModule } from './app-routing.module';\nimport { HeroesModule } from './heroes/heroes.module';\nimport { AuthModule } from './auth/auth.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/platform-browser/animations/BrowserAnimationsModule\" class=\"code-anchor\">BrowserAnimationsModule</a>,\n <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>,\n HeroesModule,\n AuthModule,\n AppRoutingModule,\n ],\n declarations: [\n AppComponent,\n ComposeMessageComponent,\n PageNotFoundComponent\n ],\n bootstrap: [ AppComponent ]\n})\nexport class AppModule {\n}\n\n</code-pane>\n\n <code-pane header=\"src/app/auth/login/login.component.html\" path=\"router/src/app/auth/login/login.component.html\">\n<h2>LOGIN</h2>\n<p>{{message}}</p>\n<p>\n <button (click)=\"login()\" *<a href=\"api/common/NgIf\" class=\"code-anchor\">ngIf</a>=\"!authService.isLoggedIn\">Login</button>\n <button (click)=\"logout()\" *<a href=\"api/common/NgIf\" class=\"code-anchor\">ngIf</a>=\"authService.isLoggedIn\">Logout</button>\n</p>\n\n</code-pane>\n\n <code-pane header=\"src/app/auth/login/login.component.ts\" path=\"router/src/app/auth/login/login.component.1.ts\">\nimport { <a href=\"api/core/Component\" class=\"code-anchor\">Component</a> } from '@angular/core';\nimport { <a href=\"api/router/Router\" class=\"code-anchor\">Router</a> } from '@angular/router';\nimport { AuthService } from '../auth.service';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-login',\n templateUrl: './login.component.html',\n styleUrls: ['./login.component.css']\n})\nexport class LoginComponent {\n message: string;\n\n constructor(public authService: AuthService, public router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) {\n this.setMessage();\n }\n\n setMessage() {\n this.message = 'Logged ' + (this.authService.isLoggedIn ? 'in' : 'out');\n }\n\n login() {\n this.message = 'Trying to log in ...';\n\n this.authService.login().subscribe(() => {\n this.setMessage();\n if (this.authService.isLoggedIn) {\n // Usually you would use the redirect URL from the auth service.\n // However to keep the example simple, we will always redirect to `/admin`.\n const redirectUrl = '/admin';\n\n // Redirect the user\n this.router.navigate([redirectUrl]);\n }\n });\n }\n\n logout() {\n this.authService.logout();\n this.setMessage();\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"src/app/auth/auth.module.ts\" path=\"router/src/app/auth/auth.module.ts\">\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';\nimport { <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a> } from '@angular/forms';\n\nimport { LoginComponent } from './login/login.component';\nimport { AuthRoutingModule } from './auth-routing.module';\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 <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>,\n AuthRoutingModule\n ],\n declarations: [\n LoginComponent\n ]\n})\nexport class AuthModule {}\n\n\n</code-pane>\n\n</code-tabs>\n<a id=\"can-activate-child-guard\"></a>\n<h3 id=\"canactivatechild-guarding-child-routes\"><code><a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a></code>: guarding child routes<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#canactivatechild-guarding-child-routes\"><i class=\"material-icons\">link</i></a></h3>\n<p>You can also protect child routes with the <code><a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a></code> guard.\nThe <code><a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a></code> guard is similar to the <code><a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a></code> guard.\nThe key difference is that it runs before any child route is activated.</p>\n<p>You protected the admin feature module from unauthorized access.\nYou should also protect child routes <em>within</em> the feature module.</p>\n<p>Extend the <code>AuthGuard</code> to protect when navigating between the <code>admin</code> routes.\nOpen <code>auth.guard.ts</code> and add the <code><a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a></code> interface to the imported tokens from the router package.</p>\n<p>Next, implement the <code>canActivateChild()</code> method which takes the same arguments as the <code>canActivate()</code> method: an <code><a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a></code> and <code><a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a></code>.\nThe <code>canActivateChild()</code> method can return an <code>Observable<boolean|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a>></code> or <code>Promise<boolean|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a>></code> for async checks and a <code>boolean</code> or <code><a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a></code> for sync checks.\nThis one returns either <code>true</code> to allow the user to access the admin feature module or <code><a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a></code> to redirect the user to the login page instead:</p>\n<code-example path=\"router/src/app/auth/auth.guard.3.ts\" header=\"src/app/auth/auth.guard.ts (excerpt)\" region=\"can-activate-child\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport {\n <a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a>, <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>,\n <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>,\n <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>,\n <a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a>,\n <a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a>\n} from '@angular/router';\nimport { AuthService } from './auth.service';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class AuthGuard implements <a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a>, <a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a> {\n constructor(private authService: AuthService, private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) {}\n\n canActivate(\n route: <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>,\n <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>): true|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a> {\n const url: string = state.url;\n\n return this.checkLogin(url);\n }\n\n canActivateChild(\n route: <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>,\n <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>): true|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a> {\n return this.canActivate(route, <a href=\"api/animations/state\" class=\"code-anchor\">state</a>);\n }\n\n/* . . . */\n}\n\n</code-example>\n<p>Add the same <code>AuthGuard</code> to the <code>component-less</code> admin route to protect all other child routes at one time\ninstead of adding the <code>AuthGuard</code> to each route individually.</p>\n<code-example path=\"router/src/app/admin/admin-routing.module.3.ts\" header=\"src/app/admin/admin-routing.module.ts (excerpt)\" region=\"can-activate-child\">\nconst adminRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n {\n path: 'admin',\n component: AdminComponent,\n canActivate: [AuthGuard],\n children: [\n {\n path: '',\n canActivateChild: [AuthGuard],\n children: [\n { path: 'crises', component: ManageCrisesComponent },\n { path: 'heroes', component: ManageHeroesComponent },\n { path: '', component: AdminDashboardComponent }\n ]\n }\n ]\n }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(adminRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class AdminRoutingModule {}\n\n</code-example>\n<a id=\"can-deactivate-guard\"></a>\n<h3 id=\"candeactivate-handling-unsaved-changes\"><code><a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a></code>: handling unsaved changes<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#candeactivate-handling-unsaved-changes\"><i class=\"material-icons\">link</i></a></h3>\n<p>Back in the \"Heroes\" workflow, the app accepts every change to a hero immediately without validation.</p>\n<p>In the real world, you might have to accumulate the users changes, validate across fields, validate on the server, or hold changes in a pending state until the user confirms them as a group or cancels and reverts all changes.</p>\n<p>When the user navigates away, you can let the user decide what to do with unsaved changes.\nIf the user cancels, you'll stay put and allow more changes.\nIf the user approves, the app can save.</p>\n<p>You still might delay navigation until the save succeeds.\nIf you let the user move to the next screen immediately and saving were to fail (perhaps the data is ruled invalid), you would lose the context of the error.</p>\n<p>You need to stop the navigation while you wait, asynchronously, for the server to return with its answer.</p>\n<p>The <code><a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a></code> guard helps you decide what to do with unsaved changes and how to proceed.</p>\n<a id=\"cancel-save\"></a>\n<h4 id=\"cancel-and-save\">Cancel and save<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#cancel-and-save\"><i class=\"material-icons\">link</i></a></h4>\n<p>Users update crisis information in the <code>CrisisDetailComponent</code>.\nUnlike the <code>HeroDetailComponent</code>, the user changes do not update the crisis entity immediately.\nInstead, the app updates the entity when the user presses the Save button and discards the changes when the user presses the Cancel button.</p>\n<p>Both buttons navigate back to the crisis list after save or cancel.</p>\n<code-example path=\"router/src/app/crisis-center/crisis-detail/crisis-detail.component.ts\" header=\"src/app/crisis-center/crisis-detail/crisis-detail.component.ts (cancel and save methods)\" region=\"cancel-save\">\ncancel() {\n this.gotoCrises();\n}\n\nsave() {\n this.crisis.name = this.editName;\n this.gotoCrises();\n}\n\n</code-example>\n<p>In this scenario, the user could click the heroes link, cancel, push the browser back button, or navigate away without saving.</p>\n<p>This example app asks the user to be explicit with a confirmation dialog box that waits asynchronously for the user's\nresponse.</p>\n<div class=\"alert is-helpful\">\n<p>You could wait for the user's answer with synchronous, blocking code, however, the app is more responsive—and can do other work—by waiting for the user's answer asynchronously.</p>\n</div>\n<p>Generate a <code>Dialog</code> service to handle user confirmation.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate service dialog\n</code-example>\n<p>Add a <code>confirm()</code> method to the <code>DialogService</code> to prompt the user to confirm their intent.\nThe <code>window.confirm</code> is a blocking action that displays a modal dialog and waits for user interaction.</p>\n<code-example path=\"router/src/app/dialog.service.ts\" header=\"src/app/dialog.service.ts\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\n/**\n * Async modal dialog service\n * DialogService makes this app easier to test by faking this service.\n * TODO: better modal implementation that doesn't use window.confirm\n */\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class DialogService {\n /**\n * Ask user to confirm an action. `message` explains the action and choices.\n * Returns observable resolving to `true`=confirm or `false`=cancel\n */\n confirm(message?: string): Observable<boolean> {\n const confirmation = window.confirm(message || 'Is it OK?');\n\n return of(confirmation);\n }\n}\n\n\n</code-example>\n<p>It returns an <code>Observable</code> that resolves when the user eventually decides what to do: either to discard changes and navigate away (<code>true</code>) or to preserve the pending changes and stay in the crisis editor (<code>false</code>).</p>\n<a id=\"CanDeactivate\"></a>\n<p>Generate a guard that checks for the presence of a <code>canDeactivate()</code> method in a component—any component.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate guard can-deactivate\n</code-example>\n<p>Paste the following code into your guard.</p>\n<code-example path=\"router/src/app/can-deactivate.guard.ts\" header=\"src/app/can-deactivate.guard.ts\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport { <a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a> } from '@angular/router';\nimport { Observable } from 'rxjs';\n\nexport interface CanComponentDeactivate {\n canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;\n}\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class CanDeactivateGuard implements <a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a><CanComponentDeactivate> {\n canDeactivate(component: CanComponentDeactivate) {\n return component.canDeactivate ? component.canDeactivate() : true;\n }\n}\n\n\n</code-example>\n<p>While the guard doesn't have to know which component has a deactivate method, it can detect that the <code>CrisisDetailComponent</code> component has the <code>canDeactivate()</code> method and call it.\nThe guard not knowing the details of any component's deactivation method makes the guard reusable.</p>\n<p>Alternatively, you could make a component-specific <code><a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a></code> guard for the <code>CrisisDetailComponent</code>.\nThe <code>canDeactivate()</code> method provides you with the current instance of the <code>component</code>, the current <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code>, and <code><a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a></code> in case you needed to access some external information.\nThis would be useful if you only wanted to use this guard for this component and needed to get the component's properties or confirm whether the router should allow navigation away from it.</p>\n<code-example path=\"router/src/app/can-deactivate.guard.1.ts\" header=\"src/app/can-deactivate.guard.ts (component-specific)\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport { Observable } from 'rxjs';\nimport { <a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a>,\n <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>,\n <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a> } from '@angular/router';\n\nimport { CrisisDetailComponent } from './crisis-center/crisis-detail/crisis-detail.component';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class CanDeactivateGuard implements <a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a><CrisisDetailComponent> {\n\n canDeactivate(\n component: CrisisDetailComponent,\n route: <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>,\n <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>\n ): Observable<boolean> | boolean {\n // Get the Crisis Center ID\n console.log(route.paramMap.get('id'));\n\n // Get the current URL\n console.log(state.url);\n\n // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged\n if (!component.crisis || component.crisis.name === component.editName) {\n return true;\n }\n // Otherwise ask the user with the dialog service and return its\n // observable which resolves to true or false when the user decides\n return component.dialogService.confirm('Discard changes?');\n }\n}\n\n\n</code-example>\n<p>Looking back at the <code>CrisisDetailComponent</code>, it implements the confirmation workflow for unsaved changes.</p>\n<code-example path=\"router/src/app/crisis-center/crisis-detail/crisis-detail.component.ts\" header=\"src/app/crisis-center/crisis-detail/crisis-detail.component.ts (excerpt)\" region=\"canDeactivate\">\ncanDeactivate(): Observable<boolean> | boolean {\n // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged\n if (!this.crisis || this.crisis.name === this.editName) {\n return true;\n }\n // Otherwise ask the user with the dialog service and return its\n // observable which resolves to true or false when the user decides\n return this.dialogService.confirm('Discard changes?');\n}\n\n</code-example>\n<p>Notice that the <code>canDeactivate()</code> method can return synchronously; it returns <code>true</code> immediately if there is no crisis or there are no pending changes.\nBut it can also return a <code>Promise</code> or an <code>Observable</code> and the router will wait for that to resolve to truthy (navigate) or falsy (stay on the current route).</p>\n<p>Add the <code>Guard</code> to the crisis detail route in <code>crisis-center-routing.module.ts</code> using the <code>canDeactivate</code> array property.</p>\n<code-example path=\"router/src/app/crisis-center/crisis-center-routing.module.3.ts\" header=\"src/app/crisis-center/crisis-center-routing.module.ts (can deactivate guard)\">\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 { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component';\nimport { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { CrisisCenterComponent } from './crisis-center/crisis-center.component';\nimport { CrisisDetailComponent } from './crisis-detail/crisis-detail.component';\n\nimport { CanDeactivateGuard } from '../can-deactivate.guard';\n\nconst crisisCenterRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n {\n path: 'crisis-center',\n component: CrisisCenterComponent,\n children: [\n {\n path: '',\n component: CrisisListComponent,\n children: [\n {\n path: ':id',\n component: CrisisDetailComponent,\n canDeactivate: [CanDeactivateGuard]\n },\n {\n path: '',\n component: CrisisCenterHomeComponent\n }\n ]\n }\n ]\n }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(crisisCenterRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class CrisisCenterRoutingModule { }\n\n\n</code-example>\n<p>Now you have given the user a safeguard against unsaved changes.</p>\n<a id=\"Resolve\"></a>\n<a id=\"resolve-guard\"></a>\n<h3 id=\"resolve-pre-fetching-component-data\"><em>Resolve</em>: pre-fetching component data<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#resolve-pre-fetching-component-data\"><i class=\"material-icons\">link</i></a></h3>\n<p>In the <code>Hero Detail</code> and <code>Crisis Detail</code>, the app waited until the route was activated to fetch the respective hero or crisis.</p>\n<p>If you were using a real world API, there might be some delay before the data to display is returned from the server.\nYou don't want to display a blank component while waiting for the data.</p>\n<p>To improve this behavior, you can pre-fetch data from the server using a resolver so it's ready the\nmoment the route is activated.\nThis also allows you to handle errors before routing to the component.\nThere's no point in navigating to a crisis detail for an <code>id</code> that doesn't have a record.\nIt'd be better to send the user back to the <code>Crisis List</code> that shows only valid crisis centers.</p>\n<p>In summary, you want to delay rendering the routed component until all necessary data has been fetched.</p>\n<a id=\"fetch-before-navigating\"></a>\n<h4 id=\"fetch-data-before-navigating\">Fetch data before navigating<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#fetch-data-before-navigating\"><i class=\"material-icons\">link</i></a></h4>\n<p>At the moment, the <code>CrisisDetailComponent</code> retrieves the selected crisis.\nIf the crisis is not found, the router navigates back to the crisis list view.</p>\n<p>The experience might be better if all of this were handled first, before the route is activated.\nA <code>CrisisDetailResolver</code> service could retrieve a <code>Crisis</code> or navigate away, if the <code>Crisis</code> did not exist, <em>before</em> activating the route and creating the <code>CrisisDetailComponent</code>.</p>\n<p>Generate a <code>CrisisDetailResolver</code> service file within the <code>Crisis Center</code> feature area.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate service crisis-center/crisis-detail-resolver\n</code-example>\n<code-example path=\"router/src/app/crisis-center/crisis-detail-resolver.service.1.ts\" header=\"src/app/crisis-center/crisis-detail-resolver.service.ts (generated)\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class CrisisDetailResolverService {\n\n constructor() { }\n\n}\n\n\n</code-example>\n<p>Move the relevant parts of the crisis retrieval logic in <code>CrisisDetailComponent.ngOnInit()</code> into the <code>CrisisDetailResolverService</code>.\nImport the <code>Crisis</code> model, <code>CrisisService</code>, and the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> so you can navigate elsewhere if you can't fetch the crisis.</p>\n<p>Be explicit and implement the <code><a href=\"api/router/Resolve\" class=\"code-anchor\">Resolve</a></code> interface with a type of <code>Crisis</code>.</p>\n<p>Inject the <code>CrisisService</code> and <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> and implement the <code>resolve()</code> method.\nThat method could return a <code>Promise</code>, an <code>Observable</code>, or a synchronous return value.</p>\n<p>The <code>CrisisService.getCrisis()</code> method returns an observable in order to prevent the route from loading until the data is fetched.\nThe <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> guards require an observable to <code>complete</code>, which means it has emitted all\nof its values.\nYou use the <code>take</code> operator with an argument of <code>1</code> to ensure that the <code>Observable</code> completes after retrieving the first value from the Observable returned by the <code>getCrisis()</code> method.</p>\n<p>If it doesn't return a valid <code>Crisis</code>, then return an empty <code>Observable</code>, cancel the previous in-progress navigation to the <code>CrisisDetailComponent</code>, and navigate the user back to the <code>CrisisListComponent</code>.\nThe updated resolver service looks like this:</p>\n<code-example path=\"router/src/app/crisis-center/crisis-detail-resolver.service.ts\" header=\"src/app/crisis-center/crisis-detail-resolver.service.ts\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport {\n <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>, <a href=\"api/router/Resolve\" class=\"code-anchor\">Resolve</a>,\n <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>,\n <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>\n} from '@angular/router';\nimport { Observable, of, EMPTY } from 'rxjs';\nimport { mergeMap, take } from 'rxjs/operators';\n\nimport { CrisisService } from './crisis.service';\nimport { Crisis } from './crisis';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class CrisisDetailResolverService implements <a href=\"api/router/Resolve\" class=\"code-anchor\">Resolve</a><Crisis> {\n constructor(private cs: CrisisService, private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) {}\n\n resolve(route: <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>, <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>): Observable<Crisis> | Observable<never> {\n const id = route.paramMap.get('id');\n\n return this.cs.getCrisis(id).pipe(\n take(1),\n mergeMap(crisis => {\n if (crisis) {\n return of(crisis);\n } else { // id not found\n this.router.navigate(['/crisis-center']);\n return EMPTY;\n }\n })\n );\n }\n}\n\n\n</code-example>\n<p>Import this resolver in the <code>crisis-center-routing.module.ts</code> and add a <code>resolve</code> object to the <code>CrisisDetailComponent</code> route configuration.</p>\n<code-example path=\"router/src/app/crisis-center/crisis-center-routing.module.4.ts\" header=\"src/app/crisis-center/crisis-center-routing.module.ts (resolver)\">\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 { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component';\nimport { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { CrisisCenterComponent } from './crisis-center/crisis-center.component';\nimport { CrisisDetailComponent } from './crisis-detail/crisis-detail.component';\n\nimport { CanDeactivateGuard } from '../can-deactivate.guard';\nimport { CrisisDetailResolverService } from './crisis-detail-resolver.service';\n\nconst crisisCenterRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n {\n path: 'crisis-center',\n component: CrisisCenterComponent,\n children: [\n {\n path: '',\n component: CrisisListComponent,\n children: [\n {\n path: ':id',\n component: CrisisDetailComponent,\n canDeactivate: [CanDeactivateGuard],\n resolve: {\n crisis: CrisisDetailResolverService\n }\n },\n {\n path: '',\n component: CrisisCenterHomeComponent\n }\n ]\n }\n ]\n }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(crisisCenterRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class CrisisCenterRoutingModule { }\n\n</code-example>\n<p>The <code>CrisisDetailComponent</code> should no longer fetch the crisis.\nWhen you re-configured the route, you changed where the crisis is.\nUpdate the <code>CrisisDetailComponent</code> to get the crisis from the <code>ActivatedRoute.data.crisis</code> property instead;</p>\n<code-example path=\"router/src/app/crisis-center/crisis-detail/crisis-detail.component.ts\" header=\"src/app/crisis-center/crisis-detail/crisis-detail.component.ts (ngOnInit v2)\" region=\"ngOnInit\">\nngOnInit() {\n this.route.data\n .subscribe((data: { crisis: Crisis }) => {\n this.editName = data.crisis.name;\n this.crisis = data.crisis;\n });\n}\n\n</code-example>\n<p>Note the following three important points:</p>\n<ol>\n<li>\n<p>The router's <code><a href=\"api/router/Resolve\" class=\"code-anchor\">Resolve</a></code> interface is optional.\nThe <code>CrisisDetailResolverService</code> doesn't inherit from a base class.\nThe router looks for that method and calls it if found.</p>\n</li>\n<li>\n<p>The router calls the resolver in any case where the user could navigate away so you don't have to code for each use case.</p>\n</li>\n<li>\n<p>Returning an empty <code>Observable</code> in at least one resolver will cancel navigation.</p>\n</li>\n</ol>\n<p>The relevant Crisis Center code for this milestone follows.</p>\n<code-tabs>\n\n <code-pane header=\"app.component.html\" path=\"router/src/app/app.component.html\">\n<h1 class=\"title\">Angular <a href=\"api/router/Router\" class=\"code-anchor\">Router</a></h1>\n<nav>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/crisis-center\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Crisis Center</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/superheroes\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Heroes</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/admin\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Admin</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/login\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Login</a>\n <a [<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]=\"[{ outlets: { popup: ['compose'] } }]\">Contact</a>\n</nav>\n<div [@routeAnimation]=\"getAnimationData(routerOutlet)\">\n <<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a> #routerOutlet=\"outlet\"></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n</div>\n<<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a> name=\"popup\"></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n\n</code-pane>\n\n <code-pane header=\"crisis-center-home.component.html\" path=\"router/src/app/crisis-center/crisis-center-home/crisis-center-home.component.html\">\n<p>Welcome to the Crisis Center</p>\n\n</code-pane>\n\n <code-pane header=\"crisis-center.component.html\" path=\"router/src/app/crisis-center/crisis-center/crisis-center.component.html\">\n<h2>CRISIS CENTER</h2>\n<<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n\n</code-pane>\n\n <code-pane header=\"crisis-center-routing.module.ts\" path=\"router/src/app/crisis-center/crisis-center-routing.module.4.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 { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component';\nimport { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { CrisisCenterComponent } from './crisis-center/crisis-center.component';\nimport { CrisisDetailComponent } from './crisis-detail/crisis-detail.component';\n\nimport { CanDeactivateGuard } from '../can-deactivate.guard';\nimport { CrisisDetailResolverService } from './crisis-detail-resolver.service';\n\nconst crisisCenterRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n {\n path: 'crisis-center',\n component: CrisisCenterComponent,\n children: [\n {\n path: '',\n component: CrisisListComponent,\n children: [\n {\n path: ':id',\n component: CrisisDetailComponent,\n canDeactivate: [CanDeactivateGuard],\n resolve: {\n crisis: CrisisDetailResolverService\n }\n },\n {\n path: '',\n component: CrisisCenterHomeComponent\n }\n ]\n }\n ]\n }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(crisisCenterRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class CrisisCenterRoutingModule { }\n\n</code-pane>\n\n <code-pane header=\"crisis-list.component.html\" path=\"router/src/app/crisis-center/crisis-list/crisis-list.component.html\">\n<ul class=\"crises\">\n <li *<a href=\"api/common/NgForOf\" class=\"code-anchor\">ngFor</a>=\"let crisis of crises$ | async\"\n [class.selected]=\"crisis.id === selectedId\">\n <a [<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]=\"[crisis.id]\">\n <span class=\"badge\">{{ crisis.id }}</span>{{ crisis.name }}\n </a>\n </li>\n</ul>\n\n<<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n\n\n</code-pane>\n\n <code-pane header=\"crisis-list.component.ts\" path=\"router/src/app/crisis-center/crisis-list/crisis-list.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';\n\nimport { CrisisService } from '../crisis.service';\nimport { Crisis } from '../crisis';\nimport { Observable } from 'rxjs';\nimport { switchMap } from 'rxjs/operators';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-crisis-list',\n templateUrl: './crisis-list.component.html',\n styleUrls: ['./crisis-list.component.css']\n})\nexport class CrisisListComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n crises$: Observable<Crisis[]>;\n selectedId: number;\n\n constructor(\n private service: CrisisService,\n private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>\n ) {}\n\n ngOnInit() {\n this.crises$ = this.route.paramMap.pipe(\n switchMap(params => {\n this.selectedId = +params.get('id');\n return this.service.getCrises();\n })\n );\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"crisis-detail.component.html\" path=\"router/src/app/crisis-center/crisis-detail/crisis-detail.component.html\">\n<div *<a href=\"api/common/NgIf\" class=\"code-anchor\">ngIf</a>=\"crisis\">\n <h3>\"{{ editName }}\"</h3>\n <div>\n <label>Id: </label>{{ crisis.id }}</div>\n <div>\n <label>Name: </label>\n <input [(<a href=\"api/forms/NgModel\" class=\"code-anchor\">ngModel</a>)]=\"editName\" placeholder=\"name\"/>\n </div>\n <p>\n <button (click)=\"save()\">Save</button>\n <button (click)=\"cancel()\">Cancel</button>\n </p>\n</div>\n\n</code-pane>\n\n <code-pane header=\"crisis-detail.component.ts\" path=\"router/src/app/crisis-center/crisis-detail/crisis-detail.component.ts\">\nimport { <a href=\"api/core/Component\" class=\"code-anchor\">Component</a>, <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a>, <a href=\"api/core/HostBinding\" class=\"code-anchor\">HostBinding</a> } from '@angular/core';\nimport { <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>, <a href=\"api/router/Router\" class=\"code-anchor\">Router</a> } from '@angular/router';\nimport { Observable } from 'rxjs';\n\nimport { Crisis } from '../crisis';\nimport { DialogService } from '../../dialog.service';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-crisis-detail',\n templateUrl: './crisis-detail.component.html',\n styleUrls: ['./crisis-detail.component.css']\n})\nexport class CrisisDetailComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n crisis: Crisis;\n editName: string;\n\n constructor(\n private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>,\n private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>,\n public dialogService: DialogService\n ) {}\n\n ngOnInit() {\n this.route.data\n .subscribe((data: { crisis: Crisis }) => {\n this.editName = data.crisis.name;\n this.crisis = data.crisis;\n });\n }\n\n cancel() {\n this.gotoCrises();\n }\n\n save() {\n this.crisis.name = this.editName;\n this.gotoCrises();\n }\n\n canDeactivate(): Observable<boolean> | boolean {\n // Allow synchronous navigation (`true`) if no crisis or the crisis is unchanged\n if (!this.crisis || this.crisis.name === this.editName) {\n return true;\n }\n // Otherwise ask the user with the dialog service and return its\n // observable which resolves to true or false when the user decides\n return this.dialogService.confirm('Discard changes?');\n }\n\n gotoCrises() {\n const crisisId = this.crisis ? this.crisis.id : null;\n // Pass along the crisis id if available\n // so that the CrisisListComponent can select that crisis.\n // Add a totally useless `foo` parameter for kicks.\n // Relative navigation back to the crises\n this.router.navigate(['../', { id: crisisId, foo: 'foo' }], { relativeTo: this.route });\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"crisis-detail-resolver.service.ts\" path=\"router/src/app/crisis-center/crisis-detail-resolver.service.ts\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport {\n <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>, <a href=\"api/router/Resolve\" class=\"code-anchor\">Resolve</a>,\n <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>,\n <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>\n} from '@angular/router';\nimport { Observable, of, EMPTY } from 'rxjs';\nimport { mergeMap, take } from 'rxjs/operators';\n\nimport { CrisisService } from './crisis.service';\nimport { Crisis } from './crisis';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class CrisisDetailResolverService implements <a href=\"api/router/Resolve\" class=\"code-anchor\">Resolve</a><Crisis> {\n constructor(private cs: CrisisService, private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) {}\n\n resolve(route: <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>, <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>): Observable<Crisis> | Observable<never> {\n const id = route.paramMap.get('id');\n\n return this.cs.getCrisis(id).pipe(\n take(1),\n mergeMap(crisis => {\n if (crisis) {\n return of(crisis);\n } else { // id not found\n this.router.navigate(['/crisis-center']);\n return EMPTY;\n }\n })\n );\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"crisis.service.ts\" path=\"router/src/app/crisis-center/crisis.service.ts\">\nimport { BehaviorSubject } from 'rxjs';\nimport { map } from 'rxjs/operators';\n\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport { MessageService } from '../message.service';\nimport { Crisis } from './crisis';\nimport { CRISES } from './mock-crises';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class CrisisService {\n <a href=\"api/upgrade/static\" class=\"code-anchor\">static</a> nextCrisisId = 100;\n private crises$: BehaviorSubject<Crisis[]> = new BehaviorSubject<Crisis[]>(CRISES);\n\n constructor(private messageService: MessageService) { }\n\n getCrises() { return this.crises$; }\n\n getCrisis(id: number | string) {\n return this.getCrises().pipe(\n map(crises => crises.find(crisis => crisis.id === +id))\n );\n }\n\n}\n\n\n</code-pane>\n\n <code-pane header=\"dialog.service.ts\" path=\"router/src/app/dialog.service.ts\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport { Observable, of } from 'rxjs';\n\n/**\n * Async modal dialog service\n * DialogService makes this app easier to test by faking this service.\n * TODO: better modal implementation that doesn't use window.confirm\n */\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class DialogService {\n /**\n * Ask user to confirm an action. `message` explains the action and choices.\n * Returns observable resolving to `true`=confirm or `false`=cancel\n */\n confirm(message?: string): Observable<boolean> {\n const confirmation = window.confirm(message || 'Is it OK?');\n\n return of(confirmation);\n }\n}\n\n\n</code-pane>\n\n</code-tabs>\n<p>Guards</p>\n<code-tabs>\n\n <code-pane header=\"auth.guard.ts\" path=\"router/src/app/auth/auth.guard.3.ts\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport {\n <a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a>, <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>,\n <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>,\n <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>,\n <a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a>,\n <a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a>\n} from '@angular/router';\nimport { AuthService } from './auth.service';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class AuthGuard implements <a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a>, <a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a> {\n constructor(private authService: AuthService, private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) {}\n\n canActivate(\n route: <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>,\n <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>): true|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a> {\n const url: string = state.url;\n\n return this.checkLogin(url);\n }\n\n canActivateChild(\n route: <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>,\n <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>): true|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a> {\n return this.canActivate(route, <a href=\"api/animations/state\" class=\"code-anchor\">state</a>);\n }\n\n checkLogin(url: string): true|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a> {\n if (this.authService.isLoggedIn) { return true; }\n\n // Store the attempted URL for redirecting\n this.authService.redirectUrl = url;\n\n // Redirect to the login page\n return this.router.parseUrl('/login');\n }\n}\n\n\n</code-pane>\n\n <code-pane header=\"can-deactivate.guard.ts\" path=\"router/src/app/can-deactivate.guard.ts\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport { <a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a> } from '@angular/router';\nimport { Observable } from 'rxjs';\n\nexport interface CanComponentDeactivate {\n canDeactivate: () => Observable<boolean> | Promise<boolean> | boolean;\n}\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class CanDeactivateGuard implements <a href=\"api/router/CanDeactivate\" class=\"code-anchor\">CanDeactivate</a><CanComponentDeactivate> {\n canDeactivate(component: CanComponentDeactivate) {\n return component.canDeactivate ? component.canDeactivate() : true;\n }\n}\n\n\n</code-pane>\n\n</code-tabs>\n<a id=\"query-parameters\"></a>\n<a id=\"fragment\"></a>\n<h3 id=\"query-parameters-and-fragments\">Query parameters and fragments<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#query-parameters-and-fragments\"><i class=\"material-icons\">link</i></a></h3>\n<p>In the <a href=\"guide/router-tutorial-toh#optional-route-parameters\">route parameters</a> section, you only dealt with parameters specific to the route.\nHowever, you can use query parameters to get optional parameters available to all routes.</p>\n<p><a href=\"https://en.wikipedia.org/wiki/Fragment_identifier\">Fragments</a> refer to certain elements on the page\nidentified with an <code>id</code> attribute.</p>\n<p>Update the <code>AuthGuard</code> to provide a <code>session_id</code> query that will remain after navigating to another route.</p>\n<p>Add an <code>anchor</code> element so you can jump to a certain point on the page.</p>\n<p>Add the <code><a href=\"api/router/NavigationExtras\" class=\"code-anchor\">NavigationExtras</a></code> object to the <code>router.navigate()</code> method that navigates you to the <code>/login</code> route.</p>\n<code-example path=\"router/src/app/auth/auth.guard.4.ts\" header=\"src/app/auth/auth.guard.ts (v3)\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport {\n <a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a>, <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>,\n <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>,\n <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>,\n <a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a>,\n <a href=\"api/router/NavigationExtras\" class=\"code-anchor\">NavigationExtras</a>,\n <a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a>\n} from '@angular/router';\nimport { AuthService } from './auth.service';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class AuthGuard implements <a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a>, <a href=\"api/router/CanActivateChild\" class=\"code-anchor\">CanActivateChild</a> {\n constructor(private authService: AuthService, private router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) {}\n\n canActivate(route: <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>, <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>): true|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a> {\n const url: string = state.url;\n\n return this.checkLogin(url);\n }\n\n canActivateChild(route: <a href=\"api/router/ActivatedRouteSnapshot\" class=\"code-anchor\">ActivatedRouteSnapshot</a>, <a href=\"api/animations/state\" class=\"code-anchor\">state</a>: <a href=\"api/router/RouterStateSnapshot\" class=\"code-anchor\">RouterStateSnapshot</a>): true|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a> {\n return this.canActivate(route, <a href=\"api/animations/state\" class=\"code-anchor\">state</a>);\n }\n\n checkLogin(url: string): true|<a href=\"api/router/UrlTree\" class=\"code-anchor\">UrlTree</a> {\n if (this.authService.isLoggedIn) { return true; }\n\n // Store the attempted URL for redirecting\n this.authService.redirectUrl = url;\n\n // Create a dummy session id\n const sessionId = 123456789;\n\n // Set our navigation extras object\n // that contains our <a href=\"api/core/global\" class=\"code-anchor\">global</a> <a href=\"api/animations/query\" class=\"code-anchor\">query</a> params and fragment\n const navigationExtras: <a href=\"api/router/NavigationExtras\" class=\"code-anchor\">NavigationExtras</a> = {\n queryParams: { session_id: sessionId },\n fragment: 'anchor'\n };\n\n // Redirect to the login page with extras\n return this.router.createUrlTree(['/login'], navigationExtras);\n }\n}\n\n\n</code-example>\n<p>You can also preserve query parameters and fragments across navigations without having to provide them again when navigating.\nIn the <code>LoginComponent</code>, you'll add an <em>object</em> as the second argument in the <code>router.navigateUrl()</code> function and provide the <code>queryParamsHandling</code> and <code>preserveFragment</code> to pass along the current query parameters and fragment to the next route.</p>\n<code-example path=\"router/src/app/auth/login/login.component.ts\" header=\"src/app/auth/login/login.component.ts (preserve)\" region=\"preserve\">\n// Set our navigation extras object\n// that passes on our <a href=\"api/core/global\" class=\"code-anchor\">global</a> <a href=\"api/animations/query\" class=\"code-anchor\">query</a> params and fragment\nconst navigationExtras: <a href=\"api/router/NavigationExtras\" class=\"code-anchor\">NavigationExtras</a> = {\n queryParamsHandling: 'preserve',\n preserveFragment: true\n};\n\n// Redirect the user\nthis.router.navigate([redirectUrl], navigationExtras);\n\n</code-example>\n<div class=\"alert is-helpful\">\n<p>The <code>queryParamsHandling</code> feature also provides a <code>merge</code> option, which preserves and combines the current query parameters with any provided query parameters when navigating.</p>\n</div>\n<p>To navigate to the Admin Dashboard route after logging in, update <code>admin-dashboard.component.ts</code> to handle the\nquery parameters and fragment.</p>\n<code-example path=\"router/src/app/admin/admin-dashboard/admin-dashboard.component.1.ts\" header=\"src/app/admin/admin-dashboard/admin-dashboard.component.ts (v2)\">\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 { Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-admin-dashboard',\n templateUrl: './admin-dashboard.component.html',\n styleUrls: ['./admin-dashboard.component.css']\n})\nexport class AdminDashboardComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n sessionId: Observable<string>;\n token: Observable<string>;\n\n constructor(private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>) {}\n\n ngOnInit() {\n // Capture the session ID if available\n this.sessionId = this.route\n .queryParamMap\n .pipe(map(params => params.get('session_id') || 'None'));\n\n // Capture the fragment if available\n this.token = this.route\n .fragment\n .pipe(map(fragment => fragment || 'None'));\n }\n}\n\n\n</code-example>\n<p>Query parameters and fragments are also available through the <code><a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a></code> service.\nJust like route parameters, the query parameters and fragments are provided as an <code>Observable</code>.\nThe updated Crisis Admin component feeds the <code>Observable</code> directly into the template using the <code><a href=\"api/common/AsyncPipe\" class=\"code-anchor\">AsyncPipe</a></code>.</p>\n<p>Now, you can click on the Admin button, which takes you to the Login page with the provided <code>queryParamMap</code> and <code>fragment</code>.\nAfter you click the login button, notice that you have been redirected to the <code>Admin Dashboard</code> page with the query parameters and fragment still intact in the address bar.</p>\n<p>You can use these persistent bits of information for things that need to be provided across pages like authentication tokens or session ids.</p>\n<div class=\"alert is-helpful\">\n<p>The <code><a href=\"api/animations/query\" class=\"code-anchor\">query</a> params</code> and <code>fragment</code> can also be preserved using a <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">RouterLink</a></code> with\nthe <code>queryParamsHandling</code> and <code>preserveFragment</code> bindings respectively.</p>\n</div>\n<a id=\"asynchronous-routing\"></a>\n<h2 id=\"milestone-6-asynchronous-routing\">Milestone 6: Asynchronous routing<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#milestone-6-asynchronous-routing\"><i class=\"material-icons\">link</i></a></h2>\n<p>As you've worked through the milestones, the application has naturally gotten larger.\nAt some point you'll reach a point where the application takes a long time to load.</p>\n<p>To remedy this issue, use asynchronous routing, which loads feature modules lazily, on request.\nLazy loading has multiple benefits.</p>\n<ul>\n<li>You can load feature areas only when requested by the user.</li>\n<li>You can speed up load time for users that only visit certain areas of the application.</li>\n<li>You can continue expanding lazy loaded feature areas without increasing the size of the initial load bundle.</li>\n</ul>\n<p>You're already part of the way there.\nBy organizing the application into modules—<code>AppModule</code>,\n<code>HeroesModule</code>, <code>AdminModule</code> and <code>CrisisCenterModule</code>—you\nhave natural candidates for lazy loading.</p>\n<p>Some modules, like <code>AppModule</code>, must be loaded from the start.\nBut others can and should be lazy loaded.\nThe <code>AdminModule</code>, for example, is needed by a few authorized users, so\nyou should only load it when requested by the right people.</p>\n<a id=\"lazy-loading-route-config\"></a>\n<h3 id=\"lazy-loading-route-configuration\">Lazy Loading route configuration<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#lazy-loading-route-configuration\"><i class=\"material-icons\">link</i></a></h3>\n<p>Change the <code>admin</code> path in the <code>admin-routing.module.ts</code> from <code>'admin'</code> to an empty string, <code>''</code>, the empty path.</p>\n<p>Use empty path routes to group routes together without adding any additional path segments to the URL.\nUsers will still visit <code>/admin</code> and the <code>AdminComponent</code> still serves as the Routing Component containing child routes.</p>\n<p>Open the <code>AppRoutingModule</code> and add a new <code>admin</code> route to its <code>appRoutes</code> array.</p>\n<p>Give it a <code>loadChildren</code> property instead of a <code>children</code> property.\nThe <code>loadChildren</code> property takes a function that returns a promise using the browser's built-in syntax for lazy loading code using dynamic imports <code>import('...')</code>.\nThe path is the location of the <code>AdminModule</code> (relative to the app root).\nAfter the code is requested and loaded, the <code>Promise</code> resolves an object that contains the <code><a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a></code>, in this case the <code>AdminModule</code>.</p>\n<code-example path=\"router/src/app/app-routing.module.5.ts\" region=\"admin-1\" header=\"app-routing.module.ts (load children)\">\n{\n path: 'admin',\n loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),\n},\n\n</code-example>\n<div class=\"alert is-important\">\n<p><em>Note</em>: When using absolute paths, the <code><a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a></code> file location must begin with <code>src/app</code> in order to resolve correctly. For custom <a href=\"https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping\">path mapping with absolute paths</a>, you must configure the <code>baseUrl</code> and <code>paths</code> properties in the project <code>tsconfig.json</code>.</p>\n</div>\n<p>When the router navigates to this route, it uses the <code>loadChildren</code> string to dynamically load the <code>AdminModule</code>.\nThen it adds the <code>AdminModule</code> routes to its current route configuration.\nFinally, it loads the requested route to the destination admin component.</p>\n<p>The lazy loading and re-configuration happen just once, when the route is first requested; the module and routes are available immediately for subsequent requests.</p>\n<div class=\"alert is-helpful\">\n<p>Angular provides a built-in module loader that supports SystemJS to load modules asynchronously. If you were\nusing another bundling tool, such as Webpack, you would use the Webpack mechanism for asynchronously loading modules.</p>\n</div>\n<p>Take the final step and detach the admin feature set from the main application.\nThe root <code>AppModule</code> must neither load nor reference the <code>AdminModule</code> or its files.</p>\n<p>In <code>app.module.ts</code>, remove the <code>AdminModule</code> import statement from the top of the file\nand remove the <code>AdminModule</code> from the NgModule's <code>imports</code> array.</p>\n<a id=\"can-load-guard\"></a>\n<h3 id=\"canload-guarding-unauthorized-loading-of-feature-modules\"><code><a href=\"api/router/CanLoad\" class=\"code-anchor\">CanLoad</a></code>: guarding unauthorized loading of feature modules<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#canload-guarding-unauthorized-loading-of-feature-modules\"><i class=\"material-icons\">link</i></a></h3>\n<p>You're already protecting the <code>AdminModule</code> with a <code><a href=\"api/router/CanActivate\" class=\"code-anchor\">CanActivate</a></code> guard that prevents unauthorized users from accessing the admin feature area.\nIt redirects to the login page if the user is not authorized.</p>\n<p>But the router is still loading the <code>AdminModule</code> even if the user can't visit any of its components.\nIdeally, you'd only load the <code>AdminModule</code> if the user is logged in.</p>\n<p>Add a <code><a href=\"api/router/CanLoad\" class=\"code-anchor\">CanLoad</a></code> guard that only loads the <code>AdminModule</code> once the user is logged in <em>and</em> attempts to access the admin feature area.</p>\n<p>The existing <code>AuthGuard</code> already has the essential logic in its <code>checkLogin()</code> method to support the <code><a href=\"api/router/CanLoad\" class=\"code-anchor\">CanLoad</a></code> guard.</p>\n<p>Open <code>auth.guard.ts</code>.\nImport the <code><a href=\"api/router/CanLoad\" class=\"code-anchor\">CanLoad</a></code> interface from <code>@angular/router</code>.\nAdd it to the <code>AuthGuard</code> class's <code>implements</code> list.\nThen implement <code>canLoad()</code> as follows:</p>\n<code-example path=\"router/src/app/auth/auth.guard.ts\" header=\"src/app/auth/auth.guard.ts (CanLoad guard)\" region=\"canLoad\">\ncanLoad(route: <a href=\"api/router/Route\" class=\"code-anchor\">Route</a>): boolean {\n const url = `/${route.path}`;\n\n return this.checkLogin(url);\n}\n\n</code-example>\n<p>The router sets the <code>canLoad()</code> method's <code>route</code> parameter to the intended destination URL.\nThe <code>checkLogin()</code> method redirects to that URL once the user has logged in.</p>\n<p>Now import the <code>AuthGuard</code> into the <code>AppRoutingModule</code> and add the <code>AuthGuard</code> to the <code>canLoad</code>\narray property for the <code>admin</code> route.\nThe completed admin route looks like this:</p>\n<code-example path=\"router/src/app/app-routing.module.5.ts\" region=\"admin\" header=\"app-routing.module.ts (lazy admin route)\">\n{\n path: 'admin',\n loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),\n canLoad: [AuthGuard]\n},\n\n</code-example>\n<a id=\"preloading\"></a>\n<h3 id=\"preloading-background-loading-of-feature-areas\">Preloading: background loading of feature areas<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#preloading-background-loading-of-feature-areas\"><i class=\"material-icons\">link</i></a></h3>\n<p>In addition to loading modules on-demand, you can load modules asynchronously with preloading.</p>\n<p>The <code>AppModule</code> is eagerly loaded when the application starts, meaning that it loads right away.\nNow the <code>AdminModule</code> loads only when the user clicks on a link, which is called lazy loading.</p>\n<p>Preloading allows you to load modules in the background so that the data is ready to render when the user activates a particular route.\nConsider the Crisis Center.\nIt isn't the first view that a user sees.\nBy default, the Heroes are the first view.\nFor the smallest initial payload and fastest launch time, you should eagerly load the <code>AppModule</code> and the <code>HeroesModule</code>.</p>\n<p>You could lazy load the Crisis Center.\nBut you're almost certain that the user will visit the Crisis Center within minutes of launching the app.\nIdeally, the app would launch with just the <code>AppModule</code> and the <code>HeroesModule</code> loaded and then, almost immediately, load the <code>CrisisCenterModule</code> in the background.\nBy the time the user navigates to the Crisis Center, its module will have been loaded and ready.</p>\n<a id=\"how-preloading\"></a>\n<h4 id=\"how-preloading-works\">How preloading works<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#how-preloading-works\"><i class=\"material-icons\">link</i></a></h4>\n<p>After each successful navigation, the router looks in its configuration for an unloaded module that it can preload.\nWhether it preloads a module, and which modules it preloads, depends upon the preload strategy.</p>\n<p>The <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> offers two preloading strategies:</p>\n<ul>\n<li>No preloading, which is the default. Lazy loaded feature areas are still loaded on-demand.</li>\n<li>Preloading of all lazy loaded feature areas.</li>\n</ul>\n<p>The router either never preloads, or preloads every lazy loaded module.\nThe <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> also supports <a href=\"guide/router-tutorial-toh#custom-preloading\">custom preloading strategies</a> for fine control over which modules to preload and when.</p>\n<p>This section guides you through updating the <code>CrisisCenterModule</code> to load lazily by default and use the <code><a href=\"api/router/PreloadAllModules\" class=\"code-anchor\">PreloadAllModules</a></code> strategy to load all lazy loaded modules.</p>\n<a id=\"lazy-load-crisis-center\"></a>\n<h4 id=\"lazy-load-the-crisis-center\">Lazy load the crisis center<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#lazy-load-the-crisis-center\"><i class=\"material-icons\">link</i></a></h4>\n<p>Update the route configuration to lazy load the <code>CrisisCenterModule</code>.\nTake the same steps you used to configure <code>AdminModule</code> for lazy loading.</p>\n<ol>\n<li>\n<p>Change the <code>crisis-center</code> path in the <code>CrisisCenterRoutingModule</code> to an empty string.</p>\n</li>\n<li>\n<p>Add a <code>crisis-center</code> route to the <code>AppRoutingModule</code>.</p>\n</li>\n<li>\n<p>Set the <code>loadChildren</code> string to load the <code>CrisisCenterModule</code>.</p>\n</li>\n<li>\n<p>Remove all mention of the <code>CrisisCenterModule</code> from <code>app.module.ts</code>.</p>\n</li>\n</ol>\n<p>Here are the updated modules <em>before enabling preload</em>:</p>\n<code-tabs>\n\n <code-pane header=\"app.module.ts\" path=\"router/src/app/app.module.ts\" region=\"preload\">\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';\nimport { <a href=\"api/platform-browser/animations/BrowserAnimationsModule\" class=\"code-anchor\">BrowserAnimationsModule</a> } from '@angular/platform-browser/animations';\n\nimport { <a href=\"api/router/Router\" class=\"code-anchor\">Router</a> } from '@angular/router';\n\nimport { AppComponent } from './app.component';\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\nimport { ComposeMessageComponent } from './compose-message/compose-message.component';\n\nimport { AppRoutingModule } from './app-routing.module';\nimport { HeroesModule } from './heroes/heroes.module';\nimport { AuthModule } from './auth/auth.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/platform-browser/animations/BrowserAnimationsModule\" class=\"code-anchor\">BrowserAnimationsModule</a>,\n <a href=\"api/forms/FormsModule\" class=\"code-anchor\">FormsModule</a>,\n HeroesModule,\n AuthModule,\n AppRoutingModule,\n ],\n declarations: [\n AppComponent,\n ComposeMessageComponent,\n PageNotFoundComponent\n ],\n bootstrap: [ AppComponent ]\n})\nexport class AppModule {\n}\n\n</code-pane>\n\n <code-pane header=\"app-routing.module.ts\" path=\"router/src/app/app-routing.module.6.ts\" region=\"preload-v1\">\nimport { <a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a> } from '@angular/core';\nimport {\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>, <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a>,\n} from '@angular/router';\n\nimport { ComposeMessageComponent } from './compose-message/compose-message.component';\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\n\nimport { AuthGuard } from './auth/auth.guard';\n\nconst appRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n {\n path: 'compose',\n component: ComposeMessageComponent,\n outlet: 'popup'\n },\n {\n path: 'admin',\n loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),\n canLoad: [AuthGuard]\n },\n {\n path: 'crisis-center',\n loadChildren: () => import('./crisis-center/crisis-center.module').then(m => m.CrisisCenterModule)\n },\n { path: '', redirectTo: '/heroes', pathMatch: 'full' },\n { path: '**', component: PageNotFoundComponent }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forRoot(\n appRoutes,\n )\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class AppRoutingModule {}\n\n\n</code-pane>\n\n <code-pane header=\"crisis-center-routing.module.ts\" path=\"router/src/app/crisis-center/crisis-center-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 { CrisisCenterHomeComponent } from './crisis-center-home/crisis-center-home.component';\nimport { CrisisListComponent } from './crisis-list/crisis-list.component';\nimport { CrisisCenterComponent } from './crisis-center/crisis-center.component';\nimport { CrisisDetailComponent } from './crisis-detail/crisis-detail.component';\n\nimport { CanDeactivateGuard } from '../can-deactivate.guard';\nimport { CrisisDetailResolverService } from './crisis-detail-resolver.service';\n\nconst crisisCenterRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n {\n path: '',\n component: CrisisCenterComponent,\n children: [\n {\n path: '',\n component: CrisisListComponent,\n children: [\n {\n path: ':id',\n component: CrisisDetailComponent,\n canDeactivate: [CanDeactivateGuard],\n resolve: {\n crisis: CrisisDetailResolverService\n }\n },\n {\n path: '',\n component: CrisisCenterHomeComponent\n }\n ]\n }\n ]\n }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(crisisCenterRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class CrisisCenterRoutingModule { }\n\n</code-pane>\n\n</code-tabs>\n<p>You could try this now and confirm that the <code>CrisisCenterModule</code> loads after you click the \"Crisis Center\" button.</p>\n<p>To enable preloading of all lazy loaded modules, import the <code><a href=\"api/router/PreloadAllModules\" class=\"code-anchor\">PreloadAllModules</a></code> token from the Angular router package.</p>\n<p>The second argument in the <code><a href=\"api/router/RouterModule#forRoot\" class=\"code-anchor\">RouterModule.forRoot()</a></code> method takes an object for additional configuration options.\nThe <code>preloadingStrategy</code> is one of those options.\nAdd the <code><a href=\"api/router/PreloadAllModules\" class=\"code-anchor\">PreloadAllModules</a></code> token to the <code>forRoot()</code> call:</p>\n<code-example path=\"router/src/app/app-routing.module.6.ts\" header=\"src/app/app-routing.module.ts (preload all)\" region=\"forRoot\">\nRouterModule.forRoot(\n appRoutes,\n {\n enableTracing: true, // <-- debugging purposes only\n preloadingStrategy: <a href=\"api/router/PreloadAllModules\" class=\"code-anchor\">PreloadAllModules</a>\n }\n)\n\n</code-example>\n<p>This configures the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> preloader to immediately load all lazy loaded routes (routes with a <code>loadChildren</code> property).</p>\n<p>When you visit <code>http://localhost:4200</code>, the <code>/heroes</code> route loads immediately upon launch and the router starts loading the <code>CrisisCenterModule</code> right after the <code>HeroesModule</code> loads.</p>\n<p>Currently, the <code>AdminModule</code> does not preload because <code><a href=\"api/router/CanLoad\" class=\"code-anchor\">CanLoad</a></code> is blocking it.</p>\n<a id=\"preload-canload\"></a>\n<h4 id=\"canload-blocks-preload\"><code><a href=\"api/router/CanLoad\" class=\"code-anchor\">CanLoad</a></code> blocks preload<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#canload-blocks-preload\"><i class=\"material-icons\">link</i></a></h4>\n<p>The <code><a href=\"api/router/PreloadAllModules\" class=\"code-anchor\">PreloadAllModules</a></code> strategy does not load feature areas protected by a <a href=\"guide/router-tutorial-toh#can-load-guard\">CanLoad</a> guard.</p>\n<p>You added a <code><a href=\"api/router/CanLoad\" class=\"code-anchor\">CanLoad</a></code> guard to the route in the <code>AdminModule</code> a few steps back to block loading of that module until the user is authorized.\nThat <code><a href=\"api/router/CanLoad\" class=\"code-anchor\">CanLoad</a></code> guard takes precedence over the preload strategy.</p>\n<p>If you want to preload a module as well as guard against unauthorized access, remove the <code>canLoad()</code> guard method and rely on the <a href=\"guide/router-tutorial-toh#can-activate-guard\">canActivate()</a> guard alone.</p>\n<a id=\"custom-preloading\"></a>\n<h3 id=\"custom-preloading-strategy\">Custom Preloading Strategy<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#custom-preloading-strategy\"><i class=\"material-icons\">link</i></a></h3>\n<p>Preloading every lazy loaded module works well in many situations.\nHowever, in consideration of things such as low bandwidth and user metrics, you can use a custom preloading strategy for specific feature modules.</p>\n<p>This section guides you through adding a custom strategy that only preloads routes whose <code>data.preload</code> flag is set to <code>true</code>.\nRecall that you can add anything to the <code>data</code> property of a route.</p>\n<p>Set the <code>data.preload</code> flag in the <code>crisis-center</code> route in the <code>AppRoutingModule</code>.</p>\n<code-example path=\"router/src/app/app-routing.module.ts\" header=\"src/app/app-routing.module.ts (route data preload)\" region=\"preload-v2\">\n{\n path: 'crisis-center',\n loadChildren: () => import('./crisis-center/crisis-center.module').then(m => m.CrisisCenterModule),\n data: { preload: true }\n},\n\n</code-example>\n<p>Generate a new <code>SelectivePreloadingStrategy</code> service.</p>\n<code-example language=\"none\" class=\"code-shell\">\n ng generate service selective-preloading-strategy\n</code-example>\n<p>Replace the contents of <code>selective-preloading-strategy.service.ts</code> with the following:</p>\n<code-example path=\"router/src/app/selective-preloading-strategy.service.ts\" header=\"src/app/selective-preloading-strategy.service.ts\">\nimport { <a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a> } from '@angular/core';\nimport { <a href=\"api/router/PreloadingStrategy\" class=\"code-anchor\">PreloadingStrategy</a>, <a href=\"api/router/Route\" class=\"code-anchor\">Route</a> } from '@angular/router';\nimport { Observable, of } from 'rxjs';\n\n@<a href=\"api/core/Injectable\" class=\"code-anchor\">Injectable</a>({\n providedIn: 'root',\n})\nexport class SelectivePreloadingStrategyService implements <a href=\"api/router/PreloadingStrategy\" class=\"code-anchor\">PreloadingStrategy</a> {\n preloadedModules: string[] = [];\n\n preload(route: <a href=\"api/router/Route\" class=\"code-anchor\">Route</a>, load: () => Observable<any>): Observable<any> {\n if (route.data && route.data.preload) {\n // add the route path to the preloaded module array\n this.preloadedModules.push(route.path);\n\n // log the route path to the console\n console.log('Preloaded: ' + route.path);\n\n return load();\n } else {\n return of(null);\n }\n }\n}\n\n\n</code-example>\n<p><code>SelectivePreloadingStrategyService</code> implements the <code><a href=\"api/router/PreloadingStrategy\" class=\"code-anchor\">PreloadingStrategy</a></code>, which has one method, <code>preload()</code>.</p>\n<p>The router calls the <code>preload()</code> method with two arguments:</p>\n<ol>\n<li>The route to consider.</li>\n<li>A loader function that can load the routed module asynchronously.</li>\n</ol>\n<p>An implementation of <code>preload</code> must return an <code>Observable</code>.\nIf the route does preload, it returns the observable returned by calling the loader function.\nIf the route does not preload, it returns an <code>Observable</code> of <code>null</code>.</p>\n<p>In this sample, the <code>preload()</code> method loads the route if the route's <code>data.preload</code> flag is truthy.</p>\n<p>As a side-effect, <code>SelectivePreloadingStrategyService</code> logs the <code>path</code> of a selected route in its public <code>preloadedModules</code> array.</p>\n<p>Shortly, you'll extend the <code>AdminDashboardComponent</code> to inject this service and display its <code>preloadedModules</code> array.</p>\n<p>But first, make a few changes to the <code>AppRoutingModule</code>.</p>\n<ol>\n<li>Import <code>SelectivePreloadingStrategyService</code> into <code>AppRoutingModule</code>.</li>\n<li>Replace the <code><a href=\"api/router/PreloadAllModules\" class=\"code-anchor\">PreloadAllModules</a></code> strategy in the call to <code>forRoot()</code> with this <code>SelectivePreloadingStrategyService</code>.</li>\n<li>Add the <code>SelectivePreloadingStrategyService</code> strategy to the <code>AppRoutingModule</code> providers array so you can inject it elsewhere in the app.</li>\n</ol>\n<p>Now edit the <code>AdminDashboardComponent</code> to display the log of preloaded routes.</p>\n<ol>\n<li>Import the <code>SelectivePreloadingStrategyService</code>.</li>\n<li>Inject it into the dashboard's constructor.</li>\n<li>Update the template to display the strategy service's <code>preloadedModules</code> array.</li>\n</ol>\n<p>Now the file is as follows:</p>\n<code-example path=\"router/src/app/admin/admin-dashboard/admin-dashboard.component.ts\" header=\"src/app/admin/admin-dashboard/admin-dashboard.component.ts (preloaded modules)\">\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 { Observable } from 'rxjs';\nimport { map } from 'rxjs/operators';\n\nimport { SelectivePreloadingStrategyService } from '../../selective-preloading-strategy.service';\n\n@<a href=\"api/core/Component\" class=\"code-anchor\">Component</a>({\n selector: 'app-admin-dashboard',\n templateUrl: './admin-dashboard.component.html',\n styleUrls: ['./admin-dashboard.component.css']\n})\nexport class AdminDashboardComponent implements <a href=\"api/core/OnInit\" class=\"code-anchor\">OnInit</a> {\n sessionId: Observable<string>;\n token: Observable<string>;\n modules: string[];\n\n constructor(\n private route: <a href=\"api/router/ActivatedRoute\" class=\"code-anchor\">ActivatedRoute</a>,\n preloadStrategy: SelectivePreloadingStrategyService\n ) {\n this.modules = preloadStrategy.preloadedModules;\n }\n\n ngOnInit() {\n // Capture the session ID if available\n this.sessionId = this.route\n .queryParamMap\n .pipe(map(params => params.get('session_id') || 'None'));\n\n // Capture the fragment if available\n this.token = this.route\n .fragment\n .pipe(map(fragment => fragment || 'None'));\n }\n}\n\n\n</code-example>\n<p>Once the application loads the initial route, the <code>CrisisCenterModule</code> is preloaded.\nVerify this by logging in to the <code>Admin</code> feature area and noting that the <code>crisis-center</code> is listed in the <code>Preloaded Modules</code>.\nIt also logs to the browser's console.</p>\n<a id=\"redirect-advanced\"></a>\n<h3 id=\"migrating-urls-with-redirects\">Migrating URLs with redirects<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#migrating-urls-with-redirects\"><i class=\"material-icons\">link</i></a></h3>\n<p>You've setup the routes for navigating around your application and used navigation imperatively and declaratively.\nBut like any application, requirements change over time.\nYou've setup links and navigation to <code>/heroes</code> and <code>/hero/:id</code> from the <code>HeroListComponent</code> and <code>HeroDetailComponent</code> components.\nIf there were a requirement that links to <code>heroes</code> become <code>superheroes</code>, you would still want the previous URLs to navigate correctly.\nYou also don't want to update every link in your application, so redirects makes refactoring routes trivial.</p>\n<a id=\"url-refactor\"></a>\n<h4 id=\"changing-heroes-to-superheroes\">Changing <code>/heroes</code> to <code>/superheroes</code><a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#changing-heroes-to-superheroes\"><i class=\"material-icons\">link</i></a></h4>\n<p>This section guides you through migrating the <code>Hero</code> routes to new URLs.\nThe <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> checks for redirects in your configuration before navigating, so each redirect is triggered when needed. To support this change, add redirects from the old routes to the new routes in the <code>heroes-routing.module</code>.</p>\n<code-example path=\"router/src/app/heroes/heroes-routing.module.ts\" header=\"src/app/heroes/heroes-routing.module.ts (heroes redirects)\">\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 { HeroListComponent } from './hero-list/hero-list.component';\nimport { HeroDetailComponent } from './hero-detail/hero-detail.component';\n\nconst heroesRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n { path: 'heroes', redirectTo: '/superheroes' },\n { path: 'hero/:id', redirectTo: '/superhero/:id' },\n { path: 'superheroes', component: HeroListComponent, data: { <a href=\"api/animations/animation\" class=\"code-anchor\">animation</a>: 'heroes' } },\n { path: 'superhero/:id', component: HeroDetailComponent, data: { <a href=\"api/animations/animation\" class=\"code-anchor\">animation</a>: 'hero' } }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forChild(heroesRoutes)\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class HeroesRoutingModule { }\n\n</code-example>\n<p>Notice two different types of redirects.\nThe first change is from <code>/heroes</code> to <code>/superheroes</code> without any parameters.\nThe second change is from <code>/hero/:id</code> to <code>/superhero/:id</code>, which includes the <code>:id</code> route parameter.\nRouter redirects also use powerful pattern-matching, so the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> inspects the URL and replaces route parameters in the <code>path</code> with their appropriate destination.\nPreviously, you navigated to a URL such as <code>/hero/15</code> with a route parameter <code>id</code> of <code>15</code>.</p>\n<div class=\"alert is-helpful\">\n<p>The <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> also supports <a href=\"guide/router-tutorial-toh#query-parameters\">query parameters</a> and the <a href=\"guide/router-tutorial-toh#fragment\">fragment</a> when using redirects.</p>\n<ul>\n<li>When using absolute redirects, the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> will use the query parameters and the fragment from the <code>redirectTo</code> in the route config.</li>\n<li>When using relative redirects, the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> use the query params and the fragment from the source URL.</li>\n</ul>\n</div>\n<p>Currently, the empty path route redirects to <code>/heroes</code>, which redirects to <code>/superheroes</code>.\nThis won't work because the <code><a href=\"api/router/Router\" class=\"code-anchor\">Router</a></code> handles redirects once at each level of routing configuration.\nThis prevents chaining of redirects, which can lead to endless redirect loops.</p>\n<p>Instead, update the empty path route in <code>app-routing.module.ts</code> to redirect to <code>/superheroes</code>.</p>\n<code-example path=\"router/src/app/app-routing.module.ts\" header=\"src/app/app-routing.module.ts (superheroes redirect)\">\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 { ComposeMessageComponent } from './compose-message/compose-message.component';\nimport { PageNotFoundComponent } from './page-not-found/page-not-found.component';\n\nimport { AuthGuard } from './auth/auth.guard';\nimport { SelectivePreloadingStrategyService } from './selective-preloading-strategy.service';\n\nconst appRoutes: <a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a> = [\n {\n path: 'compose',\n component: ComposeMessageComponent,\n outlet: 'popup'\n },\n {\n path: 'admin',\n loadChildren: () => import('./admin/admin.module').then(m => m.AdminModule),\n canLoad: [AuthGuard]\n },\n {\n path: 'crisis-center',\n loadChildren: () => import('./crisis-center/crisis-center.module').then(m => m.CrisisCenterModule),\n data: { preload: true }\n },\n { path: '', redirectTo: '/superheroes', pathMatch: 'full' },\n { path: '**', component: PageNotFoundComponent }\n];\n\n@<a href=\"api/core/NgModule\" class=\"code-anchor\">NgModule</a>({\n imports: [\n RouterModule.forRoot(\n appRoutes,\n {\n enableTracing: false, // <-- debugging purposes only\n preloadingStrategy: SelectivePreloadingStrategyService,\n }\n )\n ],\n exports: [\n <a href=\"api/router/RouterModule\" class=\"code-anchor\">RouterModule</a>\n ]\n})\nexport class AppRoutingModule { }\n\n\n</code-example>\n<p>A <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a></code> isn't tied to route configuration, so update the associated router links to remain active when the new route is active.\nUpdate the <code>app.component.ts</code> template for the <code>/heroes</code> <code><a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a></code>.</p>\n<code-example path=\"router/src/app/app.component.html\" header=\"src/app/app.component.html (superheroes active routerLink)\">\n<h1 class=\"title\">Angular <a href=\"api/router/Router\" class=\"code-anchor\">Router</a></h1>\n<nav>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/crisis-center\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Crisis Center</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/superheroes\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Heroes</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/admin\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Admin</a>\n <a <a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>=\"/login\" <a href=\"api/router/RouterLinkActive\" class=\"code-anchor\">routerLinkActive</a>=\"active\">Login</a>\n <a [<a href=\"api/router/RouterLink\" class=\"code-anchor\">routerLink</a>]=\"[{ outlets: { popup: ['compose'] } }]\">Contact</a>\n</nav>\n<div [@routeAnimation]=\"getAnimationData(routerOutlet)\">\n <<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a> #routerOutlet=\"outlet\"></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n</div>\n<<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a> name=\"popup\"></<a href=\"api/router/RouterOutlet\" class=\"code-anchor\">router-outlet</a>>\n\n</code-example>\n<p>Update the <code>goToHeroes()</code> method in the <code>hero-detail.component.ts</code> to navigate back to <code>/superheroes</code> with the optional route parameters.</p>\n<code-example path=\"router/src/app/heroes/hero-detail/hero-detail.component.ts\" region=\"redirect\" header=\"src/app/heroes/hero-detail/hero-detail.component.ts (goToHeroes)\">\ngotoHeroes(hero: Hero) {\n const heroId = hero ? hero.id : null;\n // Pass along the hero id if available\n // so that the HeroList component can select that hero.\n // Include a junk 'foo' property for fun.\n this.router.navigate(['/superheroes', { id: heroId, foo: 'foo' }]);\n}\n\n</code-example>\n<p>With the redirects setup, all previous routes now point to their new destinations and both URLs still function as intended.</p>\n<a id=\"inspect-config\"></a>\n<h3 id=\"inspect-the-routers-configuration\">Inspect the router's configuration<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#inspect-the-routers-configuration\"><i class=\"material-icons\">link</i></a></h3>\n<p>To determine if your routes are actually evaluated <a href=\"guide/router-tutorial-toh#routing-module-order\">in the proper order</a>, you can inspect the router's configuration.</p>\n<p>Do this by injecting the router and logging to the console its <code>config</code> property.\nFor example, update the <code>AppModule</code> as follows and look in the browser console window\nto see the finished route configuration.</p>\n<code-example path=\"router/src/app/app.module.7.ts\" header=\"src/app/app.module.ts (inspect the router config)\" region=\"inspect-config\">\nexport class AppModule {\n // Diagnostic only: inspect router configuration\n constructor(router: <a href=\"api/router/Router\" class=\"code-anchor\">Router</a>) {\n // Use a custom replacer to display function names in the route configs\n const replacer = (key, value) => (typeof value === 'function') ? value.name : value;\n\n console.log('<a href=\"api/router/Routes\" class=\"code-anchor\">Routes</a>: ', JSON.stringify(router.config, replacer, 2));\n }\n}\n\n</code-example>\n<a id=\"final-app\"></a>\n<h2 id=\"final-app\">Final app<a title=\"Link to this heading\" class=\"header-link\" aria-hidden=\"true\" href=\"guide/router-tutorial-toh#final-app\"><i class=\"material-icons\">link</i></a></h2>\n<p>For the completed router app, see the <live-example name=\"router\"></live-example> for the final source code.</p>\n<a id=\"link-parameters-array\"></a>\n\n \n\n\n<!-- links to this doc:\n - api/router/RouterOutlet\n - guide/deployment\n - guide/glossary\n - guide/lazy-loading-ngmodules\n - guide/router\n - guide/testing-components-scenarios\n-->\n<!-- links from this doc:\n - /cli\n - /guide/router#example-config\n - /tutorial\n - api/animations/animate\n - api/animations/animateChild\n - api/animations/animation\n - api/animations/query\n - api/animations/state\n - api/animations/style\n - api/animations/transition\n - api/animations/trigger\n - api/common/AsyncPipe\n - api/common/CommonModule\n - api/common/NgForOf\n - api/common/NgIf\n - api/core/Component\n - api/core/HostBinding\n - api/core/Injectable\n - api/core/NgModule\n - api/core/OnInit\n - api/core/global\n - api/forms/DefaultValueAccessor\n - api/forms/FormsModule\n - api/forms/NgModel\n - api/platform-browser/BrowserModule\n - api/platform-browser/animations/BrowserAnimationsModule\n - api/router/ActivatedRoute\n - api/router/ActivatedRoute#paramMap\n - api/router/ActivatedRouteSnapshot\n - api/router/CanActivate\n - api/router/CanActivateChild\n - api/router/CanDeactivate\n - api/router/CanLoad\n - api/router/NavigationExtras\n - api/router/ParamMap\n - api/router/PreloadAllModules\n - api/router/PreloadingStrategy\n - api/router/Resolve\n - api/router/Route\n - api/router/Router\n - api/router/Router#navigate\n - api/router/RouterLink\n - api/router/RouterLinkActive\n - api/router/RouterModule\n - api/router/RouterModule#forChild\n - api/router/RouterModule#forRoot\n - api/router/RouterOutlet\n - api/router/RouterState\n - api/router/RouterStateSnapshot\n - api/router/RouterStateSnapshot#url\n - api/router/Routes\n - api/router/UrlTree\n - api/upgrade/static\n - cli\n - cli/generate\n - cli/new\n - guide/animations\n - guide/architecture\n - guide/attribute-binding#class-binding\n - guide/router-tutorial-toh#a-crisis-center-with-child-routes\n - guide/router-tutorial-toh#activated-route-in-action\n - guide/router-tutorial-toh#add-a-secondary-route\n - guide/router-tutorial-toh#add-an-admin-feature-module\n - guide/router-tutorial-toh#add-heroes-functionality\n - guide/router-tutorial-toh#add-the-logincomponent\n - guide/router-tutorial-toh#add-the-router-outlet\n - guide/router-tutorial-toh#adding-routable-animations\n - guide/router-tutorial-toh#authenticate-with-authguard\n - guide/router-tutorial-toh#benefits-of-a-routing-module\n - guide/router-tutorial-toh#can-activate-child-guard\n - guide/router-tutorial-toh#can-activate-guard\n - guide/router-tutorial-toh#can-load-guard\n - guide/router-tutorial-toh#canactivate-requiring-authentication\n - guide/router-tutorial-toh#canactivatechild-guarding-child-routes\n - guide/router-tutorial-toh#cancel-and-save\n - guide/router-tutorial-toh#candeactivate-handling-unsaved-changes\n - guide/router-tutorial-toh#canload-blocks-preload\n - guide/router-tutorial-toh#canload-guarding-unauthorized-loading-of-feature-modules\n - guide/router-tutorial-toh#changing-heroes-to-superheroes\n - guide/router-tutorial-toh#child-route-configuration\n - guide/router-tutorial-toh#child-routing-component\n - guide/router-tutorial-toh#clear-secondary-routes\n - guide/router-tutorial-toh#clearing-secondary-routes\n - guide/router-tutorial-toh#component-less-route-grouping-routes-without-a-component\n - guide/router-tutorial-toh#custom-preloading\n - guide/router-tutorial-toh#custom-preloading-strategy\n - guide/router-tutorial-toh#define-a-wildcard-route\n - guide/router-tutorial-toh#define-routes\n - guide/router-tutorial-toh#displaying-multiple-routes-in-named-outlets\n - guide/router-tutorial-toh#fetch-data-before-navigating\n - guide/router-tutorial-toh#final-app\n - guide/router-tutorial-toh#fragment\n - guide/router-tutorial-toh#guard-the-admin-feature\n - guide/router-tutorial-toh#hero-feature-routing-requirements\n - guide/router-tutorial-toh#heroes-functionality\n - guide/router-tutorial-toh#heroes-list-optionally-selecting-a-hero\n - guide/router-tutorial-toh#how-preloading-works\n - guide/router-tutorial-toh#import-crisis-center-module-into-the-appmodule-routes\n - guide/router-tutorial-toh#inspect-config\n - guide/router-tutorial-toh#inspect-the-routers-configuration\n - guide/router-tutorial-toh#integrate-routing-with-your-app\n - guide/router-tutorial-toh#lazy-load-the-crisis-center\n - guide/router-tutorial-toh#lazy-loading-route-configuration\n - guide/router-tutorial-toh#link-parameters-array\n - guide/router-tutorial-toh#migrating-urls-with-redirects\n - guide/router-tutorial-toh#milestone-1-getting-started\n - guide/router-tutorial-toh#milestone-1-wrap-up\n - guide/router-tutorial-toh#milestone-2-routing-module\n - guide/router-tutorial-toh#milestone-3-heroes-feature\n - guide/router-tutorial-toh#milestone-3-wrap-up\n - guide/router-tutorial-toh#milestone-4-crisis-center-feature\n - guide/router-tutorial-toh#milestone-5-route-guards\n - guide/router-tutorial-toh#milestone-6-asynchronous-routing\n - guide/router-tutorial-toh#module-import-order\n - guide/router-tutorial-toh#navigate-to-crisis-list-with-a-relative-url\n - guide/router-tutorial-toh#navigating-back-to-the-list-component\n - guide/router-tutorial-toh#objectives\n - guide/router-tutorial-toh#observable-parammap-and-component-reuse\n - guide/router-tutorial-toh#optional-route-parameters\n - guide/router-tutorial-toh#parammap-api\n - guide/router-tutorial-toh#preloading-background-loading-of-feature-areas\n - guide/router-tutorial-toh#prerequisites\n - guide/router-tutorial-toh#query-parameters\n - guide/router-tutorial-toh#query-parameters-and-fragments\n - guide/router-tutorial-toh#redirect\n - guide/router-tutorial-toh#refactor-the-routing-configuration-into-a-routing-module\n - guide/router-tutorial-toh#register-router-and-routes\n - guide/router-tutorial-toh#relative-navigation\n - guide/router-tutorial-toh#remove-duplicate-hero-routes\n - guide/router-tutorial-toh#remove-heroes-declarations\n - guide/router-tutorial-toh#resolve-pre-fetching-component-data\n - guide/router-tutorial-toh#reuse\n - guide/router-tutorial-toh#route-definition-with-a-parameter\n - guide/router-tutorial-toh#route-parameters\n - guide/router-tutorial-toh#route-parameters-in-the-activatedroute-service\n - guide/router-tutorial-toh#route-parameters-required-or-optional\n - guide/router-tutorial-toh#router-tutorial-tour-of-heroes\n - guide/router-tutorial-toh#routing-module\n - guide/router-tutorial-toh#routing-module-order\n - guide/router-tutorial-toh#secondary-route-navigation-merging-routes-during-navigation\n - guide/router-tutorial-toh#secondary-routes\n - guide/router-tutorial-toh#set-up-redirects\n - guide/router-tutorial-toh#setting-the-route-parameters-in-the-list-view\n - guide/router-tutorial-toh#snapshot-the-no-observable-alternative\n - guide/router-tutorial-toh#the-sample-application-in-action\n - guide/router-tutorial-toh#wildcard\n - guide/singleton-services#forRoot-router\n - start\n - tutorial\n - tutorial/toh-pt4\n - https://blog.8thlight.com/uncle-bob/2014/05/08/SingleReponsibilityPrinciple.html\n - https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams\n - https://en.wikipedia.org/wiki/Fragment_identifier\n - https://github.com/angular/angular/edit/master/aio/content/guide/router-tutorial-toh.md?message=docs%3A%20describe%20your%20change...\n - https://vsavkin.tumblr.com/post/146722301646/angular-router-empty-paths-componentless-routes\n - https://www.typescriptlang.org/docs/handbook/module-resolution.html#path-mapping\n - https://www.w3.org/DesignIssues/MatrixURIs.html\n-->"
|
|
} |