diff --git a/aio/content/examples/router/src/app/app-routing.module.7.ts b/aio/content/examples/router/src/app/app-routing.module.7.ts new file mode 100644 index 0000000000..f64ff71829 --- /dev/null +++ b/aio/content/examples/router/src/app/app-routing.module.7.ts @@ -0,0 +1,11 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; // CLI imports router + +const routes: Routes = []; // sets up routes constant where you define your routes + +// configures NgModule imports and exports +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] +}) +export class AppRoutingModule { } diff --git a/aio/content/examples/router/src/app/app-routing.module.8.ts b/aio/content/examples/router/src/app/app-routing.module.8.ts new file mode 100644 index 0000000000..7186ced298 --- /dev/null +++ b/aio/content/examples/router/src/app/app-routing.module.8.ts @@ -0,0 +1,26 @@ +// #docplaster +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; // CLI imports router + +// #docregion routes, routes-with-wildcard, redirect +const routes: Routes = [ + { path: 'first-component', component: FirstComponent }, + { path: 'second-component', component: SecondComponent }, + // #enddocregion routes + { path: '', redirectTo: '/first-component', pathMatch: 'full' }, // redirect to `first-component` + { path: '**', component: FirstComponent }, + // #enddocregion redirect + { path: '**', component: PageNotFoundComponent }, // Wildcard route for a 404 page + // #docregion routes + // #docregion redirect +]; +// #enddocregion routes, routes-with-wildcard, redirect + + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] +}) +export class AppRoutingModule { } + + diff --git a/aio/content/examples/router/src/app/app-routing.module.9.ts b/aio/content/examples/router/src/app/app-routing.module.9.ts new file mode 100644 index 0000000000..cd4ddd1d70 --- /dev/null +++ b/aio/content/examples/router/src/app/app-routing.module.9.ts @@ -0,0 +1,28 @@ +// #docplaster +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; // CLI imports router + +// #docregion child-routes +const routes: Routes = [ + { path: 'first-component', + component: FirstComponent, // this is the component with the in the template + children: [ + { + path: 'child-a', // child route path + component: ChildAComponent // child route component that the router renders + }, + { + path: 'child-b', + component: ChildBComponent // another child route component that the router renders + } + ] }, +// #enddocregion child-routes + + +@NgModule({ + imports: [RouterModule.forRoot(routes)], + exports: [RouterModule] +}) +export class AppRoutingModule { } + + diff --git a/aio/content/examples/router/src/app/app.component.4.ts b/aio/content/examples/router/src/app/app.component.4.ts new file mode 100644 index 0000000000..4b47a4c66f --- /dev/null +++ b/aio/content/examples/router/src/app/app.component.4.ts @@ -0,0 +1,15 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-root', + templateUrl: 'app.component.html', + styleUrls: ['app.component.css'] +}) +export class AppComponent { +// #docregion relative-to + goToItems() { + this.router.navigate(['items'], { relativeTo: this.route }); + } +// #enddocregion relative-to + +} diff --git a/aio/content/examples/router/src/app/app.component.7.html b/aio/content/examples/router/src/app/app.component.7.html new file mode 100644 index 0000000000..a13d8a97d8 --- /dev/null +++ b/aio/content/examples/router/src/app/app.component.7.html @@ -0,0 +1,10 @@ +

Angular Router App

+ + + + diff --git a/aio/content/examples/router/src/app/app.component.8.html b/aio/content/examples/router/src/app/app.component.8.html new file mode 100644 index 0000000000..74791aa9cd --- /dev/null +++ b/aio/content/examples/router/src/app/app.component.8.html @@ -0,0 +1,26 @@ + +

First Component

+ + + + + + + + + +

First Component

+ + + + + diff --git a/aio/content/examples/router/src/app/app.module.8.ts b/aio/content/examples/router/src/app/app.module.8.ts new file mode 100644 index 0000000000..3f0b1c0c0b --- /dev/null +++ b/aio/content/examples/router/src/app/app.module.8.ts @@ -0,0 +1,17 @@ +import { BrowserModule } from '@angular/platform-browser'; +import { NgModule } from '@angular/core'; +import { AppRoutingModule } from './app-routing.module'; // CLI imports AppRoutingModule +import { AppComponent } from './app.component'; + +@NgModule({ + declarations: [ + AppComponent + ], + imports: [ + BrowserModule, + AppRoutingModule // CLI adds AppRoutingModule to the AppModule's imports array + ], + providers: [], + bootstrap: [AppComponent] +}) +export class AppModule { } diff --git a/aio/content/examples/router/src/app/heroes/hero-detail/hero-detail.component.ts b/aio/content/examples/router/src/app/heroes/hero-detail/hero-detail.component.ts index 720301d192..8f54532b65 100644 --- a/aio/content/examples/router/src/app/heroes/hero-detail/hero-detail.component.ts +++ b/aio/content/examples/router/src/app/heroes/hero-detail/hero-detail.component.ts @@ -2,7 +2,9 @@ // #docregion import { switchMap } from 'rxjs/operators'; import { Component, OnInit } from '@angular/core'; +// #docregion imports-route-info import { Router, ActivatedRoute, ParamMap } from '@angular/router'; +// #enddocregion imports-route-info import { Observable } from 'rxjs'; import { HeroService } from '../hero.service'; @@ -16,11 +18,16 @@ import { Hero } from '../hero'; export class HeroDetailComponent implements OnInit { hero$: Observable; + // #docregion activated-route constructor( private route: ActivatedRoute, + // #enddocregion activated-route private router: Router, private service: HeroService + // #docregion activated-route ) {} + // #enddocregion activated-route + ngOnInit() { this.hero$ = this.route.paramMap.pipe( diff --git a/aio/content/guide/ajs-quick-reference.md b/aio/content/guide/ajs-quick-reference.md index 994ffbd5d1..e0b1a512e4 100644 --- a/aio/content/guide/ajs-quick-reference.md +++ b/aio/content/guide/ajs-quick-reference.md @@ -415,8 +415,8 @@ The following are some of the key AngularJS built-in directives and their equiva - For more information on routing, see the [RouterLink binding](guide/router#router-link) - section of the [Routing & Navigation](guide/router) page. + For more information on routing, see [Defining a basic route](guide/router#basic-route) + in the [Routing & Navigation](guide/router) page. diff --git a/aio/content/guide/browser-support.md b/aio/content/guide/browser-support.md index 12e0ac0c1c..97492e33b7 100644 --- a/aio/content/guide/browser-support.md +++ b/aio/content/guide/browser-support.md @@ -303,7 +303,7 @@ Some features of Angular may require additional polyfills. [Router](guide/router) when using - [hash-based routing](guide/router#appendix-locationstrategy-and-browser-url-styles) + [hash-based routing](guide/router#location-strategy) diff --git a/aio/content/guide/deployment.md b/aio/content/guide/deployment.md index ed0ba4a182..10b1b39701 100644 --- a/aio/content/guide/deployment.md +++ b/aio/content/guide/deployment.md @@ -321,7 +321,7 @@ absolutely must be present when the app starts. Configure the Angular Router to defer loading of all other modules (and their associated code), either by [waiting until the app has launched](guide/router#preloading "Preloading") -or by [_lazy loading_](guide/router#asynchronous-routing "Lazy loading") +or by [_lazy loading_](guide/router#lazy-loading "Lazy loading") them on demand.
diff --git a/aio/content/guide/deprecations.md b/aio/content/guide/deprecations.md index 880affa372..cdd80f9c61 100644 --- a/aio/content/guide/deprecations.md +++ b/aio/content/guide/deprecations.md @@ -318,6 +318,7 @@ const routes: Routes = [{ {@a activatedroute-props} + ### ActivatedRoute params and queryParams properties [ActivatedRoute](api/router/ActivatedRoute) contains two [properties](api/router/ActivatedRoute#properties) that are less capable than their replacements and may be deprecated in a future Angular version. @@ -327,7 +328,7 @@ const routes: Routes = [{ | `params` | `paramMap` | | `queryParams` | `queryParamMap` | -For more information see the [Router guide](guide/router#activated-route). +For more information see the [Getting route information](guide/router#activated-route) section of the [Router guide](guide/router). {@a reflect-metadata} diff --git a/aio/content/guide/router.md b/aio/content/guide/router.md index f8bbda36b2..a6af240ae5 100644 --- a/aio/content/guide/router.md +++ b/aio/content/guide/router.md @@ -1,734 +1,548 @@ # In-app navigation with routing -The Angular **`Router`** enables navigation from one [view](guide/glossary#view "View definition") to the next -as users perform application tasks. +You want the applications you build to be as fast and responsive as possible. +In Angular, a common best practice to improve responsiveness is to build _singe-page apps_. +With single-page apps, your users stay on a single page, but their view of that page changes depending on what the user wants to do. -This guide covers the router's primary features, illustrating them through the evolution -of a small application that you can run live in the browser. +To handle the navigation from one [view](guide/glossary#view) to the next, you use the Angular _router_. +The router enables navigation by interpreting a browser URL as an instruction to change the view. - - +To explore a sample app featuring the router's primary features, see the . +## Prerequisites -## Overview +Before creating a route, you should be familiar with the following: -The browser is a familiar model of application navigation: +* [Basics of components](guide/architecture-components) +* [Basics of templates](guide/glossary#template) +* An Angular app—you can generate a basic Angular app using the [Angular CLI](cli). -* Enter a URL in the address bar and the browser navigates to a corresponding page. -* Click links on the page and the browser navigates to a new page. -* Click the browser's back and forward buttons and the browser navigates - backward and forward through the history of pages you've seen. +For an introduction to Angular with a ready-made app, see [Getting Started](start). +For a more in-depth experience of building an Angular app, see the [Tour of Heroes](tutorial) tutorial. Both guide you through using component classes and templates. -The Angular `Router` ("the router") borrows from this model. -It can interpret a browser URL as an instruction to navigate to a client-generated view. -It can pass optional parameters along to the supporting view component that help it decide what specific content to present. -You can bind the router to links on a page and it will navigate to -the appropriate application view when the user clicks a link. -You can navigate imperatively when the user clicks a button, selects from a drop box, -or in response to some other stimulus from any source. And the router logs activity -in the browser's history journal so the back and forward buttons work as well. +
{@a basics} +## Generate an app with routing enabled -## The Basics +The following command uses the Angular CLI to generate a basic Angular app with an app routing module, called `AppRoutingModule`, which is an NgModule where you can configure your routes. +The app name in the following example is `routing-app`. -This guide proceeds in phases, marked by milestones, starting from a simple two-pager -and building toward a modular, multi-view design with child routes. + + ng new routing-app --routing + -An introduction to a few core router concepts will help orient you to the details that follow. +When generating a new app, the CLI prompts you to select CSS or a CSS preprocessor. +For this example, accept the default of `CSS`. +### Adding components for routing + +To use the Angular router, an app needs to have at least two components so that it can navigate from one to the other. To create a component using the CLI, enter the following at the command line where `first` is the name of your component: + + + ng generate component first + + +Repeat this step for a second component but give it a different name. +Here, the new name is `second`. + + + ng generate component second + + +The CLI automatically appends `Component`, so if you were to write `first-component`, your component would be `FirstComponentComponent`. {@a basics-base-href} - -### *<base href>* - -Most routing applications should add a `` element to the `index.html` as the first child in the `` tag -to tell the router how to compose navigation URLs. - -If the `app` folder is the application root, as it is for the sample application, -set the `href` value *exactly* as shown here. - - - - - - -{@a basics-router-imports} - - -### Router imports - -The Angular Router is an optional service that presents a particular component view for a given URL. -It is not part of the Angular core. It is in its own library package, `@angular/router`. -Import what you need from it as you would from any other Angular package. - - - - - -
+ #### `` + This guide works with a CLI-generated Angular app. + If you are working manually, make sure that you have `` in the `` of your index.html file. + This assumes that the `app` folder is the application root, and uses `"/"`. -You'll learn about more options in the [details below](#browser-url-styles). - +
+### Importing your new components -{@a basics-config} +To use your new components, import them into `AppRoutingModule` at the top of the file, as follows: + -### Configuration - -A routed Angular application has one singleton instance of the *`Router`* service. -When the browser's URL changes, that router looks for a corresponding `Route` -from which it can determine the component to display. - -A router has no routes until you configure it. -The following example creates five route definitions, configures the router via the `RouterModule.forRoot()` method, -and adds the result to the `AppModule`'s `imports` array. - - - - - - -{@a example-config} - - -The `appRoutes` array of *routes* describes how to navigate. -Pass it to the `RouterModule.forRoot()` method in the module `imports` to configure the router. - -Each `Route` maps a URL `path` to a component. -There are _no leading slashes_ in the _path_. -The router parses and builds the final URL for you, -allowing you to use both relative and absolute paths when navigating between application views. - -The `:id` in the second route is a token for a route parameter. In a URL such as `/hero/42`, "42" -is the value of the `id` parameter. The corresponding `HeroDetailComponent` -will use that value to find and present the hero whose `id` is 42. -You'll learn more about route parameters later in this guide. - -The `data` property in the third route is a place to store arbitrary data associated with -this specific route. The data property is accessible within each activated route. Use it to store -items such as page titles, breadcrumb text, and other read-only, _static_ data. -You'll use the [resolve guard](#resolve-guard) to retrieve _dynamic_ data later in the guide. - -The **empty path** in the fourth route represents the default path for the application, -the place to go when the path in the URL is empty, as it typically is at the start. -This default route redirects to the route for the `/heroes` URL and, therefore, will display the `HeroesListComponent`. - -The `**` path in the last route is a **wildcard**. The router will select this route -if the requested URL doesn't match any paths for routes defined earlier in the configuration. -This is useful for displaying a "404 - Not Found" page or redirecting to another route. - -**The order of the routes in the configuration matters** and this is by design. The router uses a **first-match wins** -strategy when matching routes, so more specific routes should be placed above less specific routes. -In the configuration above, routes with a static path are listed first, followed by an empty path route, -that matches the default route. -The wildcard route comes last because it matches _every URL_ and should be selected _only_ if no other routes are matched first. - -If you need to see what events are happening during the navigation lifecycle, there is the **enableTracing** option as part of the router's default configuration. This outputs each router event that took place during each navigation lifecycle to the browser console. This should only be used for _debugging_ purposes. You set the `enableTracing: true` option in the object passed as the second argument to the `RouterModule.forRoot()` method. - -{@a basics-router-outlet} - - -### Router outlet - -The `RouterOutlet` is a directive from the router library that is used like a component. -It acts as a placeholder that marks the spot in the template where the router should -display the components for that outlet. - - - - <router-outlet></router-outlet> - <!-- Routed components go here --> +import { FirstComponent } from './first/first.component'; +import { SecondComponent } from './second/second.component'; -Given the configuration above, when the browser URL for this application becomes `/heroes`, -the router matches that URL to the route path `/heroes` and displays the `HeroListComponent` -as a sibling element to the `RouterOutlet` that you've placed in the host component's template. +{@a basic-route} -{@a basics-router-links} -{@a router-link} +## Defining a basic route +There are three fundamental building blocks to creating a route. -### Router links +Import the `AppRoutingModule` into `AppModule` and add it to the `imports` array. -Now you have routes configured and a place to render them, but -how do you navigate? The URL could arrive directly from the browser address bar. -But most of the time you navigate as a result of some user action such as the click of -an anchor tag. +The Angular CLI performs this step for you. +However, if you are creating an app manually or working with an existing, non-CLI app, verify that the imports and configuration are correct. +The following is the default `AppModule` using the CLI with the `--routing` flag. -Consider the following template: + + - + 1. Import `RouterModule` and `Routes` into your routing module. -The `RouterLink` directives on the anchor tags give the router control over those elements. -The navigation paths are fixed, so you can assign a string to the `routerLink` (a "one-time" binding). + The Angular CLI performs this step automatically. + The CLI also sets up a `Routes` array for your routes and configures the `imports` and `exports` arrays for `@NgModule()`. -Had the navigation path been more dynamic, you could have bound to a template expression that -returned an array of route link parameters (the _link parameters array_). -The router resolves that array into a complete URL. + + -{@a router-link-active} +1. Define your routes in your `Routes` array. + Each route in this array is a JavaScript object that contains two properties. + The first property, `path`, defines the URL path for the route. + The second property, `component`, defines the component Angular should use for the corresponding path. -### Active router links + -The `RouterLinkActive` directive toggles css classes for active `RouterLink` bindings based on the current `RouterState`. + -On each anchor tag, you see a [property binding](guide/template-syntax#property-binding) to the `RouterLinkActive` directive that look like `routerLinkActive="..."`. + 1. Add your routes to your application. -The template expression to the right of the equals (=) contains a space-delimited string of CSS classes -that the Router will add when this link is active (and remove when the link is inactive). You set the `RouterLinkActive` -directive to a string of classes such as `[routerLinkActive]="'active fluffy'"` or bind it to a component -property that returns such a string. + Now that you have defined your routes, you can add them to your application. + First, add links to the two components. + Assign the anchor tag that you want to add the route to the `routerLink` attribute. + Set the value of the attribute to the component to show when a user clicks on each link. + Next, update your component template to include ``. + This element informs Angular to update the application view with the component for the selected route. -Active route links cascade down through each level of the route tree, so parent and child router links can be active at the same time. To override this behavior, you can bind to the `[routerLinkActiveOptions]` input binding with the `{ exact: true }` expression. By using `{ exact: true }`, a given `RouterLink` will only be active if its URL is an exact match to the current URL. + +{@a route-order} -{@a basics-router-state} +### Route order - -### Router state - -After the end of each successful navigation lifecycle, the router builds a tree of `ActivatedRoute` objects -that make up the current state of the router. You can access the current `RouterState` from anywhere in the -application using the `Router` service and the `routerState` property. - -Each `ActivatedRoute` in the `RouterState` provides methods to traverse up and down the route tree -to get information from parent, child and sibling routes. +The order of routes is important because the `Router` uses a first-match wins strategy when matching routes, so more specific routes should be placed above less specific routes. +List routes with a static path first, followed by an empty path route, which matches the default route. +The [wildcard route](guide/router#setting-up-wildcard-routes) comes last because it matches every URL and the `Router` selects it only if no other routes match first. {@a activated-route} +## Getting route information -### Activated route +Often, as a user navigates your application, you want to pass information from one component to another. +For example, consider an application that displays a shopping list of grocery items. +Each item in the list has a unique `id`. +To edit an item, users click an Edit button, which opens an `EditGroceryItem` component. +You want that component to retrieve the `id` for the grocery item so it can display the right information to the user. -The route path and parameters are available through an injected router service called the -[ActivatedRoute](api/router/ActivatedRoute). -It has a great deal of useful information including: +You can use a route to pass this type of information to your application components. +To do so, you use the [ActivatedRoute](api/router/ActivatedRoute) interface. - - - +To get information from a route: - - + 1. Import `ActivatedRoute` and `ParamMap` to your component. - - - - + * [`Router`](api/router) + * [`ActivatedRoute`](api/router/ActivatedRoute) + * [`ParamMap`](api/router/ParamMap) - - - - + 1. Update the `ngOnInit()` method to access the `ActivatedRoute` and track the `id` parameter: - - - - +{@a wildcard-route-how-to} - - - - +To set up a wildcard route, add the following code to your `routes` definition. - - - - + - - - - - - - - +To display a 404 page, set up a [wildcard route](guide/router#wildcard-route-how-to) with the `component` property set to the component you'd like to use for your 404 page as follows: - - - - +The last route with the `path` of `**` is a wildcard route. +The router selects this route if the requested URL doesn't match any of the paths earlier in the list and sends the user to the `PageNotFoundComponent`. - - - - + - - - - -
- Property - - Description -
- url - + + - An `Observable` of the route path(s), represented as an array of strings for each part of the route path. + These `import` statements add several important elements that your component needs. + To learn more about each, see the following API pages: -
- data - + 1. Inject an instance of `ActivatedRoute` by adding it to your application's constructor: - An `Observable` that contains the `data` object provided for the route. Also contains any resolved values from the [resolve guard](#resolve-guard). + + -
- paramMap - + + ngOnInit() { + this.activatedRoute.queryParams.subscribe(params => { + this.name = params['name']; + }); + } + - An `Observable` that contains a [map](api/router/ParamMap) of the required and [optional parameters](#optional-route-parameters) specific to the route. The map supports retrieving single and multiple values from the same parameter. + Note: The preceding example uses a variable, `name`, and assigns it the value based on the `name` parameter. -
- queryParamMap - +## Setting up wildcard routes - An `Observable` that contains a [map](api/router/ParamMap) of the [query parameters](#query-parameters) available to all routes. - The map supports retrieving single and multiple values from the query parameter. +A well-functioning application should gracefully handle when users attempt to navigate to a part of your application that does not exist. +To add this functionality to your application, you set up a wildcard route. +The Angular router selects this route any time the requested URL doesn't match any router paths. -
- fragment - + - An `Observable` of the URL [fragment](#fragment) available to all routes. +{ path: '**', component: } -
- outlet - - The name of the `RouterOutlet` used to render the route. For an unnamed outlet, the outlet name is _primary_. +The two asterisks, `**`, indicate to Angular that this `routes` definition is a wildcard route. +For the component property, you can define any component in your application. +Common choices include an application-specific `PageNotFoundComponent`, which you can define to [display a 404 page](guide/router#404-page-how-to) to your users; or a redirect to your application's main component. +A wildcard route is the last route because it matches any URL. +For more detail on why order matters for routes, see [Route order](guide/router#route-order). -
- routeConfig - +{@a 404-page-how-to} - The route configuration used for the route that contains the origin path. +## Displaying a 404 page -
- parent - + - The route's parent `ActivatedRoute` when this route is a [child route](#child-routing-component). + -
- firstChild - +## Setting up redirects - Contains the first `ActivatedRoute` in the list of this route's child routes. +To set up a redirect, configure a route with the `path` you want to redirect from, the `component` you want to redirect to, and a `pathMatch` value that tells the router how to match the URL. -
- children - + - Contains all the [child routes](#child-routing-component) activated under the current route. +In this example, the third route is a redirect so that the router defaults to the `first-component` route. +Notice that this redirect precedes the wildcard route. +Here, `path: ''` means to use the initial relative URL (`''`). -
+For more details on `pathMatch` see [Spotlight on `pathMatch`](guide/router#pathmatch). -
+{@a nesting-routes} -Two older properties are still available. They are less capable than their replacements, discouraged, and may be deprecated in a future Angular version. +## Nesting routes -**`params`**—An `Observable` that contains the required and [optional parameters](#optional-route-parameters) specific to the route. Use `paramMap` instead. +As your application grows more complex, you may want to create routes that are relative to a component other than your root component. +These types of nested routes are called child routes. +This means you're adding a second `` to your app, because it is in addition to the `` in `AppComponent`. -**`queryParams`**—An `Observable` that contains the [query parameters](#query-parameters) available to all routes. -Use `queryParamMap` instead. +In this example, there are two additional child components, `child-a`, and `child-b`. +Here, `FirstComponent` has its own `
+ -### Router events + -During each navigation, the `Router` emits navigation events through the `Router.events` property. These events range from when the navigation starts and ends to many points in between. The full list of navigation events is displayed in the table below. +A child route is like any other route, in that it needs both a `path` and a `component`. +The one difference is that you place child routes in a `children` array within the parent route. - - - + - - + - - - - +Relative paths allow you to define paths that are relative to the current URL segment. +The following example shows a relative route to another component, `second-component`. +`FirstComponent` and `SecondComponent` are at the same level in the tree, however, the link to `SecondComponent` is situated within the `FirstComponent`, meaning that the router has to go up a level and then into the second directory to find the `SecondComponent`. +Rather than writing out the whole path to get to `SecondComponent`, you can use the `../` notation to go up a level. - - - - +In addition to `../`, you can use `./` or no leading slash to specify the current level. - - - - +Then use `relativeTo` in your navigation method. +After the link parameters array, which here contains `items`, add an object with the `relativeTo` property set to the `ActivatedRoute`, which is `this.route`. - - - - + - - - - +Sometimes, a feature of your application requires accessing a part of a route, such as a query parameter or a fragment. The Tour of Heroes app at this stage in the tutorial uses a list view in which you can click on a hero to see details. The router uses an `id` to show the correct hero's details. - - - - +import { ActivatedRoute } from '@angular/router'; +import { Observable } from 'rxjs'; +import { switchMap } from 'rxjs/operators'; - - - - + +constructor(private route: ActivatedRoute) {} + - - - - +ngOnInit() { + this.heroes$ = this.route.paramMap.pipe( + switchMap(params => { + this.selectedId = Number(params.get('id')); + return this.service.getHeroes(); + }) + ); +} - - - - +Next, in the component that you want to navigate to, import the following members. - - - - + - - - - + - - - - + ngOnInit() { + let id = this.route.snapshot.paramMap.get('id'); + this.hero$ = this.service.getHero(id); + } - - - - +{@a lazy-loading} - - - - + - - - - +In the lazy loaded module's routing module, add a route for the component. - - - - -
- Router Event - - Description -
- NavigationStart - +{@a using-relative-paths} - An [event](api/router/NavigationStart) triggered when navigation starts. +## Using relative paths -
- RouteConfigLoadStart - + - An [event](api/router/RouteConfigLoadStart) triggered before the `Router` - [lazy loads](#asynchronous-routing) a route configuration. + -
- RouteConfigLoadEnd - +### Specifying a relative route - An [event](api/router/RouteConfigLoadEnd) triggered after a route has been lazy loaded. +To specify a relative route, use the `NavigationExtras` `relativeTo` property. +In the component class, import `NavigationExtras` from the `@angular/router`. -
- RoutesRecognized - + - An [event](api/router/RoutesRecognized) triggered when the Router parses the URL and the routes are recognized. +The `navigate()` arguments configure the router to use the current route as a basis upon which to append `items`. -
- GuardsCheckStart - +The `goToItems()` method interprets the destination URI as relative to the activated route and navigates to the `items` route. - An [event](api/router/GuardsCheckStart) triggered when the Router begins the Guards phase of routing. +## Accessing query parameters and fragments -
- ChildActivationStart - +First, import the following members in the component you want to navigate from. - An [event](api/router/ChildActivationStart) triggered when the Router begins activating a route's children. + -
- ActivationStart - + - An [event](api/router/ActivationStart) triggered when the Router begins activating a route. +Next inject the activated route service: -
- GuardsCheckEnd - +Configure the class so that you have an observable, `heroes$`, a `selectedId` to hold the `id` number of the hero, and the heroes in the `ngOnInit()`, add the following code to get the `id` of the selected hero. +This code snippet assumes that you have a heroes list, a hero service, a function to get your heroes, and the HTML to render your list and details, just as in the Tour of Heroes example. - An [event](api/router/GuardsCheckEnd) triggered when the Router finishes the Guards phase of routing successfully. + +heroes$: Observable; +selectedId: number; +heroes = HEROES; -
- ResolveStart - + - An [event](api/router/ResolveStart) triggered when the Router begins the Resolve phase of routing. -
- ResolveEnd - + - An [event](api/router/ResolveEnd) triggered when the Router finishes the Resolve phase of routing successfuly. +import { Router, ActivatedRoute, ParamMap } from '@angular/router'; +import { Observable } from 'rxjs'; -
- ChildActivationEnd - +Inject `ActivatedRoute` and `Router` in the constructor of the component class so they are available to this component: - An [event](api/router/ChildActivationEnd) triggered when the Router finishes activating a route's children. -
- ActivationEnd - + item$: Observable; - An [event](api/router/ActivationStart) triggered when the Router finishes activating a route. + constructor( + private route: ActivatedRoute, + private router: Router ) {} -
- NavigationEnd - + gotoItems(item: Item) { + let heroId = item ? hero.id : null; + // Pass along the item id if available + // so that the HeroList component can select that item. + this.router.navigate(['/heroes', { id: itemId }]); + } - An [event](api/router/NavigationEnd) triggered when navigation ends successfully. + -
- NavigationCancel - +## Lazy loading modules - An [event](api/router/NavigationCancel) triggered when navigation is canceled. - This can happen when a [Route Guard](#guards) returns false during navigation, - or redirects by returning a `UrlTree`. +To lazy load Angular modules, use `loadchildren` (instead of `component`) in your `AppRoutingModule` `routes` configuration as follows: -
- NavigationError - +const routes: Routes = [ + { + path: 'items', + loadChildren: () => import('./items/items.module').then(m => m.ItemsModule) + } +]; - An [event](api/router/NavigationError) triggered when navigation fails due to an unexpected error. + -
- Scroll - + - An [event](api/router/Scroll) that represents a scrolling event. +const routes: Routes = [ + { + path: '', + component: ItemsComponent + } +]; -
+
-These events are logged to the console when the `enableTracing` option is enabled also. For an example of filtering router navigation events, visit the [router section](guide/observables-in-angular#router) of the [Observables in Angular](guide/observables-in-angular) guide. +Also be sure to remove the `ItemsModule` from the `AppModule`. For more information on lazy loading modules see [Lazy-loading feature modules](guide/lazy-loading-ngmodules). -{@a basics-summary} +{@a preloading} -### Summary +## Preloading -The application has a configured router. -The shell component has a `RouterOutlet` where it can display views produced by the router. -It has `RouterLink`s that users can click to navigate via the router. +Preloading improves UX by loading parts of your app in the background. You can preload modules or component data. -Here are the key `Router` terms and their meanings: +### Preloading modules - +To enable preloading of all lazy loaded modules, import the `PreloadAllModules` token from the Angular `router`. - + - +import { PreloadAllModules } from '@angular/router'; - + - +Still in the `AppRoutingModule`, specify your preloading strategy in `forRoot()`. - + - +RouterModule.forRoot( + appRoutes, + { + preloadingStrategy: PreloadAllModules + } +) - + - +### Preloading component data - +You can preload component data so that all elements and data on a page render at the same time when the user activates a route. To preload component data, you can use a `resolver`. - +#### Resolvers - +Create a resolver service. With the CLI, the command to generate a service is as follows: - - + + ng generate service + - +In your service, import the following router members, implement `Resolve`, and inject the `Router` service: - + - +import { Resolve } from '@angular/router'; - +... - +export class CrisisDetailResolverService implements Resolve<> { + resolve(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Observable<> { + // your logic goes here + } +} - + - +Import this resolver into your module's routing module. - + - +import { YourResolverService } from './your-resolver.service'; - + - +Add a `resolve` object to the component's `route` configuration. - + +{ + path: '/your-path', + component: YourComponent, + resolve: { + crisis: YourResolverService + } +} + - - +In the component, use an observable to get the data from the `ActivatedRoute`. - - + +ngOnInit() { + this.route.data + .subscribe((your-parameters) => { + // your data-specific code goes here + }); +} + - +For more information with a working example, see the [routing tutorial section on preloading](guide/router#preloading-background-loading-of-feature-areas). - - +## Preventing unauthorized access - +Use route guards to prevent users from navigating to parts of an app without authorization. +The following route guards are available in Angular: - +* [`CanActivate`](api/router/CanActivate) +* [`CanActivateChild`](api/router/CanActivateChild) +* [`CanDeactivate`](api/router/CanDeactivate) +* [`Resolve`](api/router/Resolve) +* [`CanLoad`](api/router/CanLoad) - +To use route guards, consider using component-less routes as this facilitates guarding child routes. - +Create a service for your guard: - - + + ng generate guard your-guard + - +In your guard class, implement the guard you want to use. +The following example uses `CanActivate` to guard the route. - + +export class YourGuard implements CanActivate { + canActivate( + next: ActivatedRouteSnapshot, + state: RouterStateSnapshot): boolean { + // your logic goes here + } +} + - +In your routing module, use the appropriate property in your `routes` configuration. +Here, `canActivate` tells the router to mediate navigation to this particular route. - + +{ + path: '/your-path', + component: YourComponent, + canActivate: [YourGuard], +} + - +For more information with a working example, see the [routing tutorial section on route guards](guide/router#milestone-5-route-guards). - - +{@a router-tutorial} - +## Router tutorial: tour of heroes - +While the [Getting Started: Tour of Heroes](tutorial) tutorial introduces general Angular concepts, this [Router Tutorial](guide/router#getting-started) goes into greater detail regarding Angular's routing capabilities. +This tutorial guides you through building upon basic router configuration to create child routes, read route parameters, lazy load NgModules, guard routes, and preload data to improve the user experience. - -
- Router Part - - Meaning -
- Router - - Displays the application component for the active URL. - Manages navigation from one component to the next. -
- RouterModule - - A separate NgModule that provides the necessary service providers - and directives for navigating through application views. -
- Routes - - Defines an array of Routes, each mapping a URL path to a component. -
- Route - - Defines how the router should navigate to a component based on a URL pattern. - Most routes consist of a path and a component type. -
- RouterOutlet - - The directive (<router-outlet>) that marks where the router displays a view. -
- RouterLink - - The directive for binding a clickable HTML element to - a route. Clicking an element with a routerLink directive - that is bound to a string or a link parameters array triggers a navigation. -
- RouterLinkActive - - The directive for adding/removing classes from an HTML element when an associated - routerLink contained on or inside the element becomes active/inactive. -
- ActivatedRoute - - A service that is provided to each route component that contains route specific - information such as route parameters, static data, resolve data, global query params, and the global fragment. -
- RouterState - - The current state of the router including a tree of the currently activated - routes together with convenience methods for traversing the route tree. -
- Link parameters array - - An array that the router interprets as a routing instruction. - You can bind that array to a RouterLink or pass the array as an argument to - the Router.navigate method. -
- Routing component - - An Angular component with a RouterOutlet that displays views based on router navigations. -
+{@a router-tutorial-overview} - - - -{@a sample-app-intro} - - -## The sample application +### Router tutorial overview This guide describes development of a multi-page routed sample application. -Along the way, it highlights design decisions and describes key features of the router such as: +Along the way, it highlights key features of the router such as: * Organizing the application features into modules. * Navigating to a component (*Heroes* link to "Heroes List"). @@ -738,20 +552,19 @@ Along the way, it highlights design decisions and describes key features of the * The `CanActivateChild` guard (checking child route access). * The `CanDeactivate` guard (ask permission to discard unsaved changes). * The `Resolve` guard (pre-fetching route data). -* Lazy loading feature modules. +* Lazy loading an `NgModule`. * The `CanLoad` guard (check before loading feature module assets). -The guide proceeds as a sequence of milestones as if you were building the app step-by-step. -But, it is not a tutorial and it glosses over details of Angular application construction -that are more thoroughly covered elsewhere in the documentation. +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 [Angular concepts](guide/architecture). +For a general introduction to angular, see the [Getting Started](start). For a more in-depth overview, see the [Tour of Heroes](tutorial) tutorial. -The full source for the final version of the app can be seen and downloaded from the . + +For a working example of the final version of the app, see the . ### The sample application in action -Imagine an application that helps the _Hero Employment Agency_ run its business. -Heroes need work and the agency finds crises for them to solve. +The sample application for this tutorial helps the Hero Employment Agency find crises for heroes to solve. The application has three main feature areas: @@ -761,8 +574,7 @@ The application has three main feature areas: Try it by clicking on this live example link. -Once the app warms up, you'll see a row of navigation buttons -and the *Heroes* view with its list of heroes. +The app renders with a row of navigation buttons and the *Heroes* view with its list of heroes. - - Select a crisis and the application takes you to a crisis editing screen. The _Crisis Detail_ appears in a child component on the same page, beneath the list. @@ -808,15 +617,10 @@ Notice that the corresponding name in the crisis list does _not_ change.
- -Unlike *Hero Detail*, which updates as you type, -*Crisis Detail* changes are temporary until you either save or discard them by pressing the "Save" or "Cancel" buttons. +Unlike *Hero Detail*, which updates as you type, *Crisis Detail* changes are temporary until you either save or discard them by pressing the "Save" or "Cancel" buttons. Both buttons navigate back to the *Crisis Center* and its list of crises. -***Do not click either button yet***. -Click the browser back button or the "Heroes" link instead. - -Up pops a dialog box. +Click the browser back button or the "Heroes" link to activate a dialog.