@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:
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:
npm start
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#link-parameters-array) 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 `