Angular Routing Course by Deborah Kurata
Angular Routing Course by Deborah Kurata
INTRODUCTION
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | [Link]/deborahk/
Module
Overview Sample Application
How Routing Works
Getting the Most from This Course
Course Outline
Page Not Found Welcome
Components
Message
App Log In
Product List
Product Detail
Edit Info
Imports Shared
...
Exports Module
Declarations
Providers
Bootstrap
How Routing Works
[Link]
import { Component } from '@angular/core';
<router-outlet></router-outlet> @Component({
templateUrl: '[Link]'
})
export class ProductListComponent { }
Url is
Changed
Display Process
Match Path
Template(s) Redirect
Activate Process
Component(s) Guards
Resolve
Data
Prerequisites
@deborahkurata
Blog Post
[Link]
Checklist
[Link]
Routing Basics
Routing to Features
Course Route Parameters
Outline Prefetching Data using Route Resolvers
Child Routes
Grouping and Component-less Routes
Styling, Animating, and Watching Routes
Secondary (Auxiliary) Routes
Route Guards
Lazy Loading
App <router-outlet
<empty> <router-outlet> name="popup"> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Messages
Found
<empty> :id/edit :id
Data Data
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Routing Basics
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | [Link]/deborahk/
Module
Overview
Setting up Basic Routing
HTML 5 vs. Hash-based Urls
App
<empty> <router-outlet> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Product List Messages
Found
Primary Routes
Secondary Routes
Child Routes
Setting up Routing
Define base path
Import Router
Configure routes
Place template
Activate routes
Defining the Base Path
Service
Configuration
RouterModule Directives
- RouterLink
- RouterLinkActive
- RouterOutlet
Importing the Angular Router
[Link]
import { RouterModule } from '@angular/router';
...
@NgModule({
imports: [
BrowserModule,
RouterModule
],
declarations: [
...
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Importing the Angular Router
[Link]() [Link]()
Declares the router directives Declares the router directives
Manages our route configuration Manages our route configuration
Registers the router service Does NOT register the router service
Used once for the application Used in feature modules
Importing the Angular Router
[Link]
import { RouterModule } from '@angular/router';
...
@NgModule({
imports: [
BrowserModule,
[Link]([])
],
declarations: [
AppComponent
],
bootstrap: [AppComponent]
})
export class AppModule { }
App
<empty> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Product List Messages
Found
<router-outlet> <router-outlet>
Primary Routes
Secondary Routes
Child Routes </router-outlet> </router-outlet>
Configuring Routes
[
{ path: 'welcome', component: WelcomeComponent },
{ path: '', redirectTo: 'welcome', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
]
Redirects
[
{ path: 'home',
'welcome',
component:
component:
WelcomeComponent
WelcomeComponent
}, },
{ path: 'welcome',
'', redirectTo:
redirectTo:
'welcome',
'home',
pathMatch:
pathMatch:
'full'
'full'
}, },
{ path: '',
'**',
redirectTo:
component:'home',
'welcome',
PageNotFoundComponent
pathMatch:
pathMatch:
'full'
'full'
} }, },
]{ path: '**', component: PageNotFoundComponent }
]
Placing the Templates
[Link]
...
...
Browser Server
[Link]/APM/welcome APM/welcome
- APM
404! - [Link]
Browser Url Styles
Browser Server
[Link]/APM/welcome APM/[Link]
- APM
[Link] - [Link]
Browser Url Styles
Browser Server
[Link]/APM/#/welcome APM/
- APM
[Link] - [Link]
Using Hash-based Urls
[Link]
import { RouterModule } from '@angular/router';
...
@NgModule({
imports: [
BrowserModule,
[Link]([...], { useHash: true })
],
declarations: [
...
],
bootstrap: [ AppComponent ]
})
export class AppModule { }
Basics Checklist: Setting Up
Import RouterModule
- Use [Link]() for app
routes (one time only!)
- Use [Link]() for features
@NgModule({
imports: [
...,
[Link]([])
], ...
})
Basics Checklist: Configuring Routes
path: Url segment(s) for the route
- No leading slash
- '' for default route; '**' for wildcard route
- Casing matters
component
- Not string name; not enclosed in quotes
- Component must be imported
Order matters!
{ path: 'welcome', component: WelcomeComponent },
{ path: '', redirectTo: 'welcome', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
Basics Checklist: Placing the Template
<router-outlet></router-outlet>
Basics Checklist: Activating a Route
Page Not
Welcome Log In Product List Messages
Found
Primary Routes
Secondary Routes
Child Routes
Routing to Features
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | [Link]/deborahk/
Feature Module
An Angular module created with the express purpose of
organizing the components for a specific application
feature area.
BrowserModule HttpModule RouterModule ...
AppModule
Welcome
App Component
Component
Product Detail
Login Component
Component
Imports
Exports
Product Edit
Declarations Message Component
Component
Providers
Bootstrap
BrowserModule RouterModule
Feature Modules
HttpModule ...
Imports Shared
...
Exports Module
Declarations
Providers
Bootstrap
Module
Overview Setting up for Feature Routing
Route Path Naming Strategies
Activating a Route with Code
Accessing Feature Routes
Defining a Routing Module
App
<empty> <router-outlet> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Product List Messages
Found
Primary Routes
Secondary Routes
Child Routes
Setting up for Feature Routing
Import Router
Configure routes
Activate routes
Importing the Angular Router
Service
RouterModule Configuration
Directives
Importing the Angular Router
[Link]
import { RouterModule } from '@angular/router';
...
@NgModule({
imports: [
SharedModule,
[Link]([])
],
declarations: [
ProductListComponent,
...
],
...
})
export class ProductModule { }
Route Path Naming Strategies
Product Product
List List
products products
Product Product
Detail Detail
product/:id products/:id
Product Product
Edit Edit
productEdit/:id products/:id/edit
App
<empty> <router-outlet> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Product List Messages
Found
products/:id products/:id/edit
Product
Product Edit
Detail
Primary Routes
Secondary Routes
Child Routes
Activating a Route with Code
Activating a Route with Code
[Link]
import { Router } from '@angular/router';
...
@Component({...})
export class AppComponent {
...
constructor(private router: Router) { }
logOut(): void {
// Do some processing
[Link](['/welcome']);
}
}
Activating a Route with Code
[Link](['/welcome']); // Standard syntax
[Link] // navigate()
[Link] // navigateByUrl()
Demo
• Better organization
• Easier to find
• Separation of concerns
Matching Routes
[Link] Route Paths
imports: [
BrowserModule,
HttpModule, welcome
AppRoutingModule,
ProductModule,
''
UserModule,
MessageModule
**
] products
login
Matching Routes
[Link] Route Paths
imports: [
BrowserModule,
HttpModule, products
ProductModule,
UserModule,
login
MessageModule,
AppRoutingModule
welcome
] ''
**
Defining a Configuration Constant
[Link]
const ROUTES = [
{ path: 'welcome', component: WelcomeComponent },
{ path: '', redirectTo: 'welcome', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
];
@NgModule({
imports: [
[Link](ROUTES)
],
exports: [ RouterModule ]
})
export class AppRoutingModule { }
Routing to Features Checklist: Configuration
Import RouterModule
- Be sure to use [Link]()
[Link]('/welcome');
Routing to Features Checklist: Routing Modules
Page Not
Welcome Log In Product List Messages
Found
products/:id products/:id/edit
Product
Product Edit
Detail
Primary Routes
Secondary Routes
Child Routes
Route Parameters
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | [Link]/deborahk/
[Link]
Module
Required Parameters
Overview
- Configure
- Populate
- Read
Optional Parameters
Query Parameters
App
<empty> <router-outlet> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Product List Messages
Found
products/:id products/:id/edit
Product
Product Edit
Detail
Primary Routes
Secondary Routes
Child Routes
Configuring Routes with Placeholders
Angular Module
[
{ path: 'products', component: ProductListComponent },
{ path: 'products/:id', component: ProductDetailComponent },
{ path: 'products/:id/edit', component: ProductEditComponent }
]
Configuring Routes with Placeholders
Angular Module
[
{ path: 'orders', component: OrderListComponent },
{ path: 'orders/:id', component: OrderDetailComponent },
{ path: 'orders/:id/items/:itemId', component: OrderItemDetailComponent }
]
Populating Route Parameters
Template
Component Class
[Link](['/products', [Link]]);
Reading Route Parameters
ActivatedRoute Service
Url Route Query Resolver
…
segments parameters parameters data
Reading Route Parameters
Component Class
constructor(private route: ActivatedRoute) { }
Snapshot
let id = [Link]['id'];
Observable
[Link](
params => {
let id = params['id'];
}
);
Reading Route Parameters: Snapshot
Component Class
import { ActivatedRoute } from '@angular/router';
...
constructor(private route: ActivatedRoute) {
[Link]([Link]['id']);
}
Angular Module
{ path: 'products/:id', component: ProductDetailComponent }
Template
<a [routerLink]="['/products', [Link]]">{{[Link]}}</a>
Reading Route Parameters: Observable
Component Class
import { ActivatedRoute } from '@angular/router';
...
constructor(private route: ActivatedRoute) {
[Link](
params => {
[Link](params['id']);
}
);
}
Angular Module
{ path: 'products/:id/edit', component: ProductEditComponent }
Template
<a [routerLink]="['/products', [Link], 'edit']">Edit</a>
Reading Route Parameters
Snapshot Observable
To read the parameters only once To watch for parameter changes
Simple code More complex code
let id = [Link](
[Link]['id']; params => {
let id = params['id']);
}
);
Reading Route Parameters (v4+)
Component Class
import { ActivatedRoute } from '@angular/router';
...
constructor(private route: ActivatedRoute) {
[Link]([Link]('id'));
}
[routerLink]="['/products',
productName, productCode, availabilityStart, availabilityEnd]"
[Link]
{ path: 'products/:name/:code/:startDate/:endDate',
component: ProductListComponent }
With Optional
Parameters
March 1, 2015
[Link]
startDate=March%201%2C%202015;endDate=March%201%2C%202017
Template
[routerLink]="['/products', {name: productName, code: productCode,
startDate: availabilityStart, endDate: availabilityEnd}]"
[Link]
[Link]
Defining Query Parameters
Template
<a [routerLink] = "['/products', [Link]]"
[Link]]">
[queryParams] = "{ filterBy: 'er', showImage: true }">
{{[Link]}}
{{[Link]}}
</a>
</a>
Component Class
[Link](['/products'],
{
queryParams: { filterBy: 'er', showImage: true }
}
);
Angular Module
Component Class
[Link](['/products'],
{ preserveQueryParams: true }
);
Retaining Query Parameters (v4+)
Template
<a [routerLink] = "['/products']"
queryParamsHandling = "preserve">
Back
</a>
Component Class
[Link](['/products'],
{ queryParamsHandling: 'preserve' }
);
Reading Query Parameters
ActivatedRoute Service
Url Route Query Resolver
…
segments parameters parameters data
Reading Query Parameters
Component Class
import { ActivatedRoute } from '@angular/router';
Template
<a [routerLink] = "['/products', [Link]]"
[queryParams] = "{ filterBy: listFilter, showImage: showImage }">
{{[Link]}}
</a>
Route Parameters Checklist: Required Parameters
Populate
<a [routerLink]="['/products', [Link]]">...</a>
[Link](['/products', [Link]]);
Read
[Link]['id'];
Or Observable
Route Parameters Checklist: Optional Parameters
[Link](['/products',
{start: startDate, end: endDate}]);
Read
[Link]['start'];
Or Observable
Route Parameters Checklist: Query Parameters
[Link](['/products', {
queryParams: { filterBy: 'x', showImage: true }
}]);
Read
[Link]['filterBy'];
Or Observable
Required Parameters
Summary
- Configure
- Populate
- Read
Optional Parameters
Query Parameters
App
<empty> <router-outlet> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Product List Messages
Found
products/:id products/:id/edit
Product
Product Edit
Detail
Primary Routes
Secondary Routes
Child Routes
Prefetching Data Using Route Resolvers
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | [Link]/deborahk/
Benefits of Prefetching Data
Page Not
Welcome Log In Product List Messages
Found
products/:id products/:id/edit
Product
Product Edit
Detail
Primary Routes
Secondary Routes
Child Routes
Providing Data with a Route
Optional
Route Query
Route
Parameters Parameters
Parameters
Component Class
[Link] = [Link]['pageTitle'];
Without a Route Resolver
Web Server
Data
DB
/products/5
Router
With a Route Resolver
Web Server
Data
DB
/products/5
Router
Data
Using a Route Resolver
@Injectable()
export class ProductResolver implements Resolve<IProduct> {
resolve(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<IProduct> {
...
}
}
Adding a Resolver to a Route Configuration
Angular Module
[
{ path: 'products', component: ProductListComponent },
{ path: 'products/:id', component: ProductDetailComponent,
resolve: { product: ProductResolver }},
{ path: 'products/:id/edit', component: ProductEditComponent,
resolve: { product: ProductResolver }}
]
Adding a Resolver to a Route Configuration
Angular Module
[
{ path: 'products', component: ProductListComponent },
{ path: 'products/:id', component: ProductDetailComponent,
resolve: { product: ProductResolver }},
{ path: 'products/:id/edit', component: ProductEditComponent,
resolve: { product: ProductResolver,
categories: CategoryResolver }}
]
Reading Resolver Data: Snapshot
Component Class
import { ActivatedRoute } from '@angular/router';
...
product: IProduct;
Angular Module
{ path: 'products/:id', component: ProductDetailComponent,
resolve: { product: ProductResolver } }
Resolver Service
export class ProductResolver implements Resolve<IProduct> { }
Sharing the Data Instance
Router
Data:
product
Component Class 1
[Link] = [Link]['product'];
Component Class 2
[Link] = [Link]['product'];
Reading Resolver Data: Observables
Component Class
import { ActivatedRoute } from '@angular/router';
...
product: IProduct;
constructor(private route: ActivatedRoute) {
[Link](
data => [Link] = data['product'];
);
}
Angular Module
{ path: 'products/:id/edit', component: ProductEditComponent,
resolve: { product: ProductResolver } }
Resolver Service
export class ProductResolver implements Resolve<IProduct> { }
Route Resolvers Checklist: Building
resolve(route: ActivatedRouteSnapshot,
state: RouterStateSnapshot): Observable<IProduct> { }
Route Resolvers Checklist: Configuring
[Link] = [Link]['product'];
- Data Observable
[Link](
data => [Link] = data['product'];
);
Providing Data with a Route
Page Not
Welcome Log In Product List Messages
Found
products/:id products/:id/edit
Product
Product Edit
Detail
Primary Routes
Secondary Routes
Child Routes
Child Routes
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | [Link]/deborahk/
App
/welcome /products
Welcome
/ /:id/edit /:id
Product
Product List Product Edit
Detail
/info /tags
Page Not
Welcome Log In Product List Messages
Found
products/:id products/:id/edit
Product
Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Secondary Routes Edit Info Edit Tags
Child Routes
Primary Router Outlet
[Link]
<div>
<nav class="navbar navbar-default">
<div class="container-fluid">
<a class="navbar-brand">{{pageTitle}}</a>
<ul class="nav navbar-nav">
<li><a [routerLink]="['/welcome']">Home</a></li>
<li><a [routerLink]="['/products']">Product List</a></li>
<li><a [routerLink]="['/products', 0, 'edit']">Add Product</a></li>
</ul>
...
</div>
</nav>
<div class="container">
<router-outlet></router-outlet>
</div>
</div>
<router-outlet>
<router-outlet></router-outlet>
</router-outlet>
<router-outlet>
</router-outlet>
<router-outlet>
<router-outlet></router-outlet>
</router-outlet>
<router-outlet>
<router-outlet>
</router-outlet>
</router-outlet>
Child Routes
Tabbed pages
Master/detail layouts
Embedded templates
Feature modules
Lazy loading
App
<router-outlet>
welcome products products/:id/edit products/:id
Product
Welcome Product List Product Edit
Detail
<router-outlet>
info tags
<router-outlet></router-outlet>
</div>
Activating Child Routes
Template
// Absolute path
<a [routerLink]="['/products', [Link], 'edit', 'info']">Info</a>
// Relative path
<a [routerLink]="['info']">Info</a>
Component Class
// Absolute path
[Link](['/products', [Link], 'edit', 'info']);
// Relative path
[Link](['info'], { relativeTo: [Link] });
Obtaining Data for a Child Route
Product Data Service
•@
[Link](id)
•@
.subscribe(product => [Link] = product);
•@
•@
Product
Welcome Product List Product Edit
Detail
<router-outlet>
info tags
<router-outlet></router-outlet>
</div>
Child Routes: Activating
[Link] = [Link]['product'];
- Data Observable
[Link](
data => [Link] = data['product'];
);
Using Child Routes
Summary Configuring Child Routes
Placing the Child View
Activating Child Routes
Obtaining Data for Child Routes
Validating Across Child Routes
App
<empty> <router-outlet> (popup:
welcome login products ** messages)
Data Data
Page Not
Welcome Log In Product List Messages
Found
products/:id products/:id/edit
Product
Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Secondary Routes Edit Info Edit Tags
Child Routes
Grouping and Component-less Routes
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | [Link]/deborahk/
App
<router-outlet>
/welcome /products
Welcome
/ /:id/edit /:id
Product
Product List Product Edit
Detail
<router-outlet>
/info /tags
Better organization
Share resolvers and guards
Lazy loading
Module
Overview
Grouping Routes
Component-less Routes
App
<empty> <router-outlet> (popup:
welcome login products ** messages)
Data Data
Page Not
Welcome Log In Product List Messages
Found
products/:id products/:id/edit
Product
Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Secondary Routes Edit Info Edit Tags
Child Routes
App
<empty> <router-outlet> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Messages
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Grouping Routes
[Link]([ [Link]([
{ {
path: 'products', path: 'products',
component: ProductListComponent component: ProductListComponent,
}, children: [
{ {
path: 'products/:id', path: ':id',
component: ProductDetailComponent, component: ProductDetailComponent,
resolve: { product: ProductResolver } resolve: { product: ProductResolver }
}, },
{ {
path: 'products/:id/edit', path: ':id/edit',
component: ProductEditComponent, component: ProductEditComponent,
resolve: { product: ProductResolver }, resolve: { product: ProductResolver },
children: [...] children: [...]
} }
]) ]
])
<router-outlet>
<router-outlet></router-outlet>
</router-outlet>
<router-outlet>
<router-outlet>
</router-outlet>
</router-outlet>
<router-outlet>
<router-outlet></router-outlet>
</router-outlet>
Component-less Route
[Link]([ [Link]([
{ {
path: 'products', path: 'products',
component: ProductListComponent, children: [
children: [ {
{ path: '',
path: ':id', component: ProductListComponent
component: ProductDetailComponent, },
resolve: { product: ProductResolver } {
}, path: ':id',
{ component: ProductDetailComponent,
path: ':id/edit', resolve: { product: ProductResolver }
component: ProductEditComponent, },
resolve: { product: ProductResolver }, {
children: [...] path: ':id/edit',
} component: ProductEditComponent,
] resolve: { product: ProductResolver },
]) children: [...]
}
]
])
App
<empty> <router-outlet> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Messages
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Checklist: Grouping
[Link]([
{
path: 'products',
component: ProductListComponent,
children: [
{ Define routes as children of one
path: ':id', parent route
component: ProductDetailComponent,
resolve: { product: ProductResolver }
},
Specify relative paths
{
path: ':id/edit', But grouping alone is not sufficient!
component: ProductEditComponent,
resolve: { product: ProductResolver },
children: [...]
}
]
])
Checklist: Component-less Routes
[Link]([
{
path: 'products',
children: [
{ Add a default path that routes to the
path: '',
component: ProductListComponent desired component
},
{ Remove the component from the
path: ':id', parent route
component: ProductDetailComponent,
resolve: { product: ProductResolver } The child routes are displayed in a
},
{ higher-level outlet
path: ':id/edit',
component: ProductEditComponent,
resolve: { product: ProductResolver },
children: [...]
}
])
Summary
Grouping Routes
Component-less Routes
App
<empty> <router-outlet> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Messages
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Styling, Animating, and
Watching Routes
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | [Link]/deborahk/
Module
Overview Styling the Selected Route
Animating Route Transitions
Watching Routing Events
Reacting to Routing Events
App
<empty> <router-outlet> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Messages
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Styling the Selected Route
Styling the Selected Route
Template
NavigationCancel NavigationError
Watching Routing Events
[Link]
imports: [
[Link]([
{ path: 'welcome', component: WelcomeComponent },
{ path: '', redirectTo: 'welcome', pathMatch: 'full' },
{ path: '**', component: PageNotFoundComponent }
], { enableTracing: true })
],
...
Reacting to Routing Events
Display a spinner
Log actions
Execute logic
Reacting to Routing Events
Component Class
Page Not
Welcome Log In Messages
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Secondary Routes
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | [Link]/deborahk/
<app-graph> <app-stats>
<app-pie> <app-map>
<router-outlet> <router-outlet>
<router-outlet> <router-outlet>
Module
Overview Using Secondary Routes
Defining a Named RouterOutlet
Configuring Secondary Routes
Activating Secondary Routes
Clearing Secondary Outlets
App <router-outlet
<empty> <router-outlet> name="popup"> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Messages
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Primary Router Outlet
[Link]
<div>
<nav class="navbar navbar-default">
<div class="container-fluid">
<a class="navbar-brand">{{pageTitle}}</a>
<ul class="nav navbar-nav">
<li><a [routerLink]="['/welcome']">Home</a></li>
<li><a [routerLink]="['/products']">Product List</a></li>
<li><a [routerLink]="['/products', 0, 'edit']">Add Product</a></li>
</ul>
...
</div>
</nav>
<div class="container">
<router-outlet></router-outlet>
</div>
</div>
<router-outlet> <router-outlet>
</router-outlet> </router-outlet>
Secondary Routes
Dashboard
Multi-window user interface
Notes or comments
Messages
…
<router-outlet> <router-outlet>name="popup">
<router-outlet
</router-outlet> </router-outlet>
</router-outlet>
</router-outlet> </router-outlet>
Configuring Secondary Routes
Angular Module
[Link]([
{
path: 'messages',
component: MessageComponent,
outlet: 'popup'
},
])
<router-outlet> App <router-outlet name="popup">
Welcome Log In
Product
Message
<empty> :id/edit :id Summary
[Link]([{ outlets: {
primary: ['/products', [Link], 'edit'],
popup: ['summary', [Link]]
}}]);
[Link]('/products/5/edit(popup:summary/5)');
Clearing Secondary Outlets
Template
Component Class
[Link]('/login');
Secondary Routes: Named RouterOutlet
<router-outlet name='popup'></router-outlet>
</div>
Secondary Routes: Configuring
Page Not
Welcome Log In Messages
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Route Guards
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR | MVP | GDE
@deborahkurata | [Link]/deborahk/
Protecting Routes with Guards
canActivate
- Guard navigation to a route
canActivateChild
- Guard navigation to a child route
canDeactivate
- Guard navigation away from a route
canLoad
- Prevent asynchronous routing
resolve
- Prefetch data before activating a route
Module
Overview Using Route Guards
canActivate Guard
Sharing Data with a Guard
canActivateChild Guard
canDeactivate Guard
App <router-outlet
<empty> <router-outlet> name="popup"> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Messages
Found
<empty> :id/edit :id
Data Data
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Using Route Guards
canDeactivate
canLoad
canActivateChild
canActivate
resolve
Building a Guard Service
[Link]
import { Injectable } from '@angular/core';
import { CanActivate } from '@angular/router';
@Injectable()
export class AuthGuard implements CanActivate {
canActivate(): boolean {
...
}
}
Registering a Guard
Angular Module
...
import { AuthGuard } from './[Link]';
@NgModule({
imports: [...],
declarations: [...],
providers: [ AuthGuard, ... ]
})
export class UserModule { }
Guarding a Route
Angular Module
...
import { AuthGuard } from './[Link]';
...
{
path: ':id',
component: ProductDetailComponent,
resolve: { product: ProductResolver },
canActivate: [ AuthGuard ]
}
Sharing Guards
[Link]([
{
path: 'products',
children: [
{
path: '',
component: ProductListComponent
},
{
path: ':id',
component: ProductDetailComponent,
resolve: { product: ProductResolver }
},
{
path: ':id/edit',
component: ProductEditComponent,
resolve: { product: ProductResolver },
children: [...]
}
]
])
Guarding a Route
Register the
Build a guard Add the guard
service in an
service to a route
Angular module
canActivate Guard
Page Not
Welcome Log In Messages
Found
<empty> :id/edit :id
Data Data
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
canDeactivate Guard
Build a service
Implement the guard type
Create the associated method
Register the service provider
@NgModule({
import { Injectable
Add } from '@angular/core';
the guard to a route
import { CanActivate } from
imports: [...],'@angular/router';
{ declarations: [...],
@Injectable()
path: ':id', [ AuthGuard, ... ]
providers:
export classcanActivate:
AuthGuard implements CanActivate
[ AuthGuard ], {
})
component: ProductDetailComponent
canActivate(): boolean {...}
}
},
Summary Using Route Guards
canActivate Guard
Sharing Data with a Guard
canActivateChild Guard
canDeactivate Guard
App <router-outlet
<empty> <router-outlet> name="popup"> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Messages
Found
<empty> :id/edit :id
Data Data
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Lazy Loading
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR
@deborahkurata | [Link]/deborahk/
Web
Web Browser Server
[Link]
Response
App Files
Web
Web Browser Server
[Link]
Response
App Files
Lazy
Loaded
Files
Module
Overview Preparing for Lazy Loading
Lazy Loading
canLoad Guard
Preloading Feature Modules
Custom Loading Strategies
App <router-outlet
<empty> <router-outlet> name="popup"> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Messages
Found
<empty> :id/edit :id
Data Data
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Preparing for Lazy Loading
Navigate Download
Download
Launch Template to a lazy lazy Template
imported
application appears loaded loaded appears
modules
feature module
Navigate
Download
Launch Template Preload to lazy Template
imported
application appears modules loaded appears
modules
feature
Preload Strategies
No
Preload all Custom
preloading
Preload All Strategy
[Link]
import { RouterModule, PreloadAllModules } from '@angular/router';
...
[Link]([
{ path: 'welcome', component: WelcomeComponent },
{
path: 'products',
loadChildren: 'app/products/[Link]#ProductModule'
},
...
], { preloadingStrategy: PreloadAllModules })
canLoad guard
blocks
preloading
Preload Strategies
No
Preload all Custom
preloading
Custom Preloading Strategy
Set the
Build a Register the
preloading
preloading service in an
strategy routing
strategy service Angular module
option
Building a Preload Strategy Service
[Link]
import { Injectable } from '@angular/core';
import { PreloadingStrategy } from '@angular/router';
import { Observable } from '@angular/router';
@Injectable()
export class SelectiveStrategy implements PreloadingStrategy {
@NgModule({
imports: [
[Link]([
{ path: 'welcome', component: WelcomeComponent },
{
path: 'products',
loadChildren: 'app/products/[Link]#ProductModule'
}, ...
], { preloadingStrategy: SelectiveStrategy }),
],
providers: [ SelectiveStrategy, ... ]
})
export class AppModule { }
Lazy Loading Checklist: Preparing
{
path: 'products',
loadChildren: 'app/products/[Link]#ProductModule'
}
Lazy Loading Checklist: Preloading
Page Not
Welcome Log In Messages
Found
<empty> :id/edit :id
Data Data
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Final Words
Deborah Kurata
CONSULTANT | SPEAKER | AUTHOR
@deborahkurata | [Link]/deborahk/
App
<empty> <router-outlet>
welcome **
Page Not
Welcome
Found
Primary Routes
Secondary Routes
Child Routes
App
<empty> <router-outlet>
welcome login products **
Page Not
Welcome Log In Product List
Found
Primary Routes
Secondary Routes
Child Routes
App
<empty> <router-outlet>
welcome login products **
Page Not
Welcome Log In Product List
Found
products/:id products/:id/edit
Product
Product Edit
Detail
Primary Routes
Secondary Routes
Child Routes
App
<empty> <router-outlet>
welcome login products **
Data Data
Page Not
Welcome Log In Product List
Found
products/:id products/:id/edit
Product
Product Edit
Detail
Primary Routes
Secondary Routes
Child Routes
App
<empty> <router-outlet>
welcome login products **
Data Data
Page Not
Welcome Log In Product List
Found
products/:id products/:id/edit
Product
Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Secondary Routes Edit Info Edit Tags
Child Routes
App
<empty> <router-outlet>
welcome login products **
Page Not
Welcome Log In
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
App
<empty> <router-outlet>
welcome login products **
Page Not
Welcome Log In
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
App <router-outlet
<empty> <router-outlet> name="popup">
welcome login products ** (popup: messages)
Page Not
Welcome Log In Messages
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
App <router-outlet
<empty> <router-outlet> name="popup"> (popup:
welcome login products ** messages)
Page Not
Welcome Log In Messages
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
App <router-outlet
<empty> <router-outlet> name="popup">
welcome login products ** (popup: messages)
Page Not
Welcome Log In Messages
Found
Product
Product List Product Edit
Detail
<router-outlet>
info tags
Primary Routes
Edit Info Edit Tags
Secondary Routes
Child Routes
Checklist
Book
- "Angular Router" by Victor Savkin
• [Link]
@deborahkurata