@title Routing @intro Add the Angular component router and learn to navigate among the views. @description There are new requirements for the Tour of Heroes app: * Add a *Dashboard* view. * Add the ability to navigate between the *Heroes* and *Dashboard* views. * When users click a hero name in either view, navigate to a detail view of the selected hero. * When users click a *deep link* in an email, open the detail view for a particular hero. When you’re done, users will be able to navigate the app like this:
View navigations
To satisfy these requirements, you'll add Angular’s router to the app. ~~~ {.l-sub-section} For more information about the router, read the [Routing and Navigation](guide/router) page. ~~~ When you're done with this page, the app should look like this . ## Where you left off Before continuing with the Tour of Heroes, verify that you have the following structure. angular-tour-of-heroes src app app.component.ts app.module.ts hero.service.ts hero.ts hero-detail.component.ts mock-heroes.ts main.ts index.html styles.css systemjs.config.js tsconfig.json node_modules ... package.json ## Keep the app transpiling and running Enter the following command in the terminal window: code-example(language="sh" class="code-shell"). npm start :marked This command runs the TypeScript compiler in "watch mode", recompiling automatically when the code changes. The command simultaneously launches the app in a browser and refreshes the browser when the code changes. You can keep building the Tour of Heroes without pausing to recompile or refresh the browser. ## Action plan Here's the plan: * Turn `AppComponent` into an application shell that only handles navigation. * Relocate the *Heroes* concerns within the current `AppComponent` to a separate `HeroesComponent`. * Add routing. * Create a new `DashboardComponent`. * Tie the *Dashboard* into the navigation structure. ~~~ {.l-sub-section} *Routing* is another name for *navigation*. The router is the mechanism for navigating from view to view. ~~~ ## Splitting the *AppComponent* The current app loads `AppComponent` and immediately displays the list of heroes. The revised app should present a shell with a choice of views (*Dashboard* and *Heroes*) and then default to one of them. The `AppComponent` should only handle navigation, so you'll move the display of *Heroes* out of `AppComponent` and into its own `HeroesComponent`. ### *HeroesComponent* `AppComponent` is already dedicated to *Heroes*. Instead of moving the code out of `AppComponent`, rename it to `HeroesComponent` and create a separate `AppComponent` shell. Do the following: * Rename the app.component.ts file to heroes.component.ts. * Rename the `AppComponent` class as `HeroesComponent` (rename locally, _only_ in this file). * Rename the selector `my-app` as `my-heroes`. ### Create *AppComponent* The new `AppComponent` is the application shell. It will have some navigation links at the top and a display area below. Perform these steps: * Create the file src/app/app.component.ts. * Define an exported `AppComponent` class. * Add an `@Component` decorator above the class with a `my-app` selector. * Move the following from `HeroesComponent` to `AppComponent`: * `title` class property. * `@Component` template `

` element, which contains a binding to `title`. * Add a `` element to the app template just below the heading so you still see the heroes. * Add `HeroesComponent` to the `declarations` array of `AppModule` so Angular recognizes the `` tags. * Add `HeroService` to the `providers` array of `AppModule` because you'll need it in every other view. * Remove `HeroService` from the `HeroesComponent` `providers` array since it was promoted. * Add the supporting `import` statements for `AppComponent`. The first draft looks like this: The app still runs and displays heroes. ## Add routing Instead of displaying automatically, heroes should display after users click a button. In other words, users should be able to navigate to the list of heroes. Use the Angular router to enable navigation. The Angular router is an external, optional Angular NgModule called `RouterModule`. The router is a combination of multiple provided services (`RouterModule`), multiple directives (`RouterOutlet, RouterLink, RouterLinkActive`), and a configuration (`Routes`). You'll configure the routes first. ### *<base href>* Open `index.html` and ensure there is a `` element (or a script that dynamically sets this element) at the top of the `` section. ~~~ {.callout.is-important}
base href is essential
For more information, see the [Set the base href](guide/router) section of the [Routing and Navigation](guide/router) page. ~~~ {@a configure-routes} ### Configure routes Create a configuration file for the app routes. *Routes* tell the router which views to display when a user clicks a link or pastes a URL into the browser address bar. Define the first route as a route to the heroes component. The `Routes` are an array of *route definitions*. This route definition has the following parts: - *Path*: The router matches this route's path to the URL in the browser address bar (`heroes`). - *Component*: The component that the router should create when navigating to this route (`HeroesComponent`). ~~~ {.l-sub-section} Read more about defining routes with `Routes` in the [Routing & Navigation](guide/router) page. ~~~ ### Make the router available Import the `RouterModule` and add it to the `AppModule` imports array. ~~~ {.l-sub-section} The `forRoot()` method is called because a configured router is provided at the app's root. The `forRoot()` method supplies the Router service providers and directives needed for routing, and performs the initial navigation based on the current browser URL. ~~~ ### Router outlet If you paste the path, `/heroes`, into the browser address bar at the end of the URL, the router should match it to the `heroes` route and display the `HeroesComponent`. However, you have to tell the router where to display the component. To do this, you can add a `` element at the end of the template. `RouterOutlet` is one of the directives provided by the `RouterModule`. The router displays each component immediately below the `` as users navigate through the app. ### Router links Users shouldn't have to paste a route URL into the address bar. Instead, add an anchor tag to the template that, when clicked, triggers navigation to the `HeroesComponent`. The revised template looks like this: Note the `routerLink` binding in the anchor tag. The `RouterLink` directive (another of the `RouterModule` directives) is bound to a string that tells the router where to navigate when the user clicks the link. Since the link is not dynamic, a routing instruction is defined with a one-time binding to the route path. Looking back at the route configuration, you can confirm that `'/heroes'` is the path of the route to the `HeroesComponent`. ~~~ {.l-sub-section} Read more about dynamic router links and the link parameters array in the [Appendix: Link Parameters Array](guide/router) section of the [Routing & Navigation](guide/router) page. ~~~ Refresh the browser. The browser displays the app title and heroes link, but not the heroes list. ~~~ {.l-sub-section} The browser's address bar shows `/`. The route path to `HeroesComponent` is `/heroes`, not `/`. Soon you'll add a route that matches the path `/`. ~~~ Click the *Heroes* navigation link. The address bar updates to `/heroes` and the list of heroes displays. `AppComponent` now looks like this: The *AppComponent* is now attached to a router and displays routed views. For this reason, and to distinguish it from other kinds of components, this component type is called a *router component*. ## Add a dashboard Routing only makes sense when multiple views exist. To add another view, create a placeholder `DashboardComponent`, which users can navigate to and from. You'll make this component more useful later. ### Configure the dashboard route To teach `app.module.ts` to navigate to the dashboard, import the dashboard component and add the following route definition to the `Routes` array of definitions. Also import and add `DashboardComponent` to the `AppModule`'s `declarations`. ### Add a !{_redirect} route Currently, the browser launches with `/` in the address bar. When the app starts, it should show the dashboard and display a `/dashboard` URL in the browser address bar. To make this happen, use a redirect route. Add the following to the array of route definitions: ~~~ {.l-sub-section} Read more about *redirects* in the [Redirecting routes](guide/router) section of the [Routing & Navigation](guide/router) page. ~~~ ### Add navigation to the template Add a dashboard navigation link to the template, just above the *Heroes* link. ~~~ {.l-sub-section} The `