Quick Reference ("How Do I...")
Navigate your Aurelia 2 application with confidence using this task-focused quick reference.
Table of Contents
Getting Started
How do I install and configure the router?
// Install
npm i @aurelia/router
// Configure in main.ts
import { RouterConfiguration } from '@aurelia/router';
Aurelia
.register(RouterConfiguration.customize({
useUrlFragmentHash: false, // Clean URLs (default)
historyStrategy: 'push', // Browser history
}))
.app(MyApp)
.start();How do I define routes?
import { route } from '@aurelia/router';
@route({
routes: [
{ path: '', component: Home, title: 'Home' },
{ path: 'about', component: About, title: 'About' },
{ path: 'users/:id', component: UserDetail }
]
})
export class MyApp {}How do I set up a viewport?
<!-- In your root component template -->
<nav>
<a href="home">Home</a>
<a href="about">About</a>
</nav>
<au-viewport></au-viewport>How do I use hash-based routing instead of clean URLs?
RouterConfiguration.customize({
useUrlFragmentHash: true // URLs like /#/about
})Navigation
How do I create navigation links?
<!-- Using href (simple) -->
<a href="about">About</a>
<a href="users/42">User 42</a>
<!-- Using load (structured) -->
<a load="route: users; params.bind: {id: userId}">User Profile</a>How do I navigate programmatically?
import { IRouter } from '@aurelia/router';
import { resolve } from '@aurelia/kernel';
export class MyComponent {
private readonly router = resolve(IRouter);
navigateToUser(id: number) {
this.router.load(`users/${id}`);
// Or with options
this.router.load('users', {
params: { id },
queryParams: { tab: 'profile' }
});
}
}How do I highlight the active link?
// Configure active class globally
RouterConfiguration.customize({
activeClass: 'active'
})<!-- Use with load attribute -->
<a load="home" active.bind="isHomeActive">Home</a>
<!-- Or use the configured active class -->
<a load="home">Home</a> <!-- Gets 'active' class automatically -->How do I navigate to parent routes from nested components?
<!-- Using href with ../ prefix -->
<a href="../sibling">Go to sibling route</a>
<!-- Using load with context -->
<a load="route: sibling; context.bind: parentContext">Sibling</a>How do I pass query parameters?
// Programmatically
router.load('search', {
queryParams: { q: 'aurelia', page: 1 }
});
// Result: /search?q=aurelia&page=1How do I handle external links?
Good news: External links work automatically! The router automatically ignores:
<!-- These automatically bypass the router (no special attributes needed!) -->
<a href="https://example.com">External site</a>
<a href="mailto:[email protected]">Email</a>
<a href="tel:+1234567890">Phone</a>
<a href="//cdn.example.com/file.pdf">Protocol-relative</a>
<a href="ftp://files.example.com">FTP</a>
<!-- Also bypassed: -->
<a href="/internal" target="_blank">New tab</a>
<a href="/internal" target="other">Named target</a>Only use external attribute for edge cases:
<!-- When URL looks internal but should bypass router -->
<a href="/api/download" external>API endpoint</a>
<a href="/old-page.html" external>Legacy HTML page</a>How it works: The router uses the URL constructor to check if a link is external. Any URL that can be parsed without a base (like https://, mailto:, etc.) is automatically treated as external.
Route Parameters
How do I define route parameters?
@route({
routes: [
{ path: 'users/:id', component: UserDetail }, // Required
{ path: 'posts/:id?', component: PostDetail }, // Optional
{ path: 'files/*path', component: FileViewer }, // Wildcard
{ path: 'items/:id{{^\\d+$}}', component: ItemDetail }, // Constrained
]
})How do I access route parameters in my component?
import { IRouteViewModel, Params } from '@aurelia/router';
export class UserDetail implements IRouteViewModel {
userId: string;
canLoad(params: Params) {
this.userId = params.id;
return true;
}
}How do I get all parameters including from parent routes?
import { IRouteContext } from '@aurelia/router';
import { resolve } from '@aurelia/kernel';
export class NestedComponent {
private readonly routeContext = resolve(IRouteContext);
attached() {
const allParams = this.routeContext.getRouteParameters<{
companyId: string;
projectId: string;
userId: string;
}>({ includeQueryParams: true });
}
}Aggregate parameters → Route parameters guide →
How do I constrain parameters with regex?
{
path: 'users/:id{{^\\d+$}}', // Only numbers
component: UserDetail
}Route Protection
How do I protect routes (authentication)?
import { lifecycleHooks } from '@aurelia/runtime-html';
import { IRouteViewModel, Params, RouteNode } from '@aurelia/router';
@lifecycleHooks()
export class AuthHook {
canLoad(viewModel: IRouteViewModel, params: Params, next: RouteNode) {
const isLoggedIn = !!localStorage.getItem('authToken');
if (!isLoggedIn) {
return 'login'; // Redirect to login
}
return true; // Allow navigation
}
}How do I implement authorization (role-based access)?
@lifecycleHooks()
export class AuthorizationHook {
canLoad(viewModel: IRouteViewModel, params: Params, next: RouteNode) {
const requiredPermission = next.data?.permission;
if (requiredPermission && !this.hasPermission(requiredPermission)) {
return 'forbidden';
}
return true;
}
private hasPermission(permission: string): boolean {
// Check user permissions
return true;
}
}// In route configuration
{
path: 'admin',
component: AdminPanel,
data: { permission: 'admin' }
}How do I prevent navigation away from unsaved forms?
import { IRouteViewModel, RouteNode } from '@aurelia/router';
export class EditForm implements IRouteViewModel {
private isDirty = false;
canUnload(next: RouteNode | null, current: RouteNode) {
if (this.isDirty) {
return confirm('You have unsaved changes. Leave anyway?');
}
return true;
}
}How do I redirect based on conditions?
export class Dashboard implements IRouteViewModel {
canLoad(params: Params) {
const userRole = this.authService.getRole();
if (userRole === 'admin') {
return 'admin/dashboard';
} else if (userRole === 'user') {
return 'user/dashboard';
}
return 'login';
}
}Lifecycle Hooks
How do I load data before showing a component?
import { IRouteViewModel, Params } from '@aurelia/router';
export class UserDetail implements IRouteViewModel {
user: User | null = null;
async loading(params: Params) {
this.user = await fetch(`/api/users/${params.id}`)
.then(r => r.json());
}
}How do I run code after a component is fully loaded?
export class Dashboard implements IRouteViewModel {
loaded(params: Params) {
// Track page view
analytics.track('page_view', { page: 'dashboard' });
// Scroll to top
window.scrollTo(0, 0);
}
}When do lifecycle hooks run?
canLoad
Before activation
Guards, redirects, param validation
loading
After approval, before render
Data fetching, state setup
loaded
After render
Analytics, scroll, post-render effects
canUnload
Before deactivation
Unsaved changes warnings
unloading
Before removal
Cleanup, save drafts
What's the difference between component hooks and router hooks?
Component hooks (
IRouteViewModel): Implemented on the component itselfRouter hooks (
@lifecycleHooks()): Shared across multiple components
// Component hook
export class MyComponent implements IRouteViewModel {
canLoad(params: Params) {
// Runs only for this component
}
}
// Router hook (shared)
@lifecycleHooks()
export class AuthHook {
canLoad(viewModel: IRouteViewModel, params: Params) {
// Runs for all components where this is registered
}
}Router hooks vs component hooks →
Advanced Topics
How do I handle 404 / unknown routes?
@route({
routes: [
{ path: 'home', component: Home },
{ path: 'about', component: About },
{ path: 'not-found', component: NotFound }
],
fallback: 'not-found' // Redirect unknown routes here
})
export class MyApp {}How do I create route aliases / redirects?
@route({
routes: [
{ path: '', redirectTo: 'home' },
{ path: 'about-us', redirectTo: 'about' },
{ path: 'home', component: Home },
{ path: 'about', component: About }
]
})How do I work with multiple viewports (sibling routes)?
<au-viewport name="left"></au-viewport>
<au-viewport name="right"></au-viewport><!-- Load components into both viewports -->
<a href="products@left+details/42@right">Products + Details</a>// Programmatically
router.load([
{ component: Products, viewport: 'left' },
{ component: Details, params: { id: 42 }, viewport: 'right' }
]);How do I implement nested/child routes?
@route({
routes: [
{
path: 'users/:id',
component: UserLayout,
// Child routes defined in UserLayout
}
]
})
export class MyApp {}
// In UserLayout
@route({
routes: [
{ path: '', component: UserProfile },
{ path: 'posts', component: UserPosts },
{ path: 'settings', component: UserSettings }
]
})
export class UserLayout {}<!-- UserLayout template -->
<h2>User: ${userId}</h2>
<nav>
<a href="posts">Posts</a>
<a href="settings">Settings</a>
</nav>
<au-viewport></au-viewport>Hierarchical routing → Child routing playbook →
How do I lazy load routes?
@route({
routes: [
{ path: 'home', component: Home },
// Dynamic import for lazy loading
{ path: 'admin', component: () => import('./admin/admin-panel') }
]
})How do I set/change the page title?
// In route configuration
{
path: 'about',
component: About,
title: 'About Us'
}
// Programmatically
router.load('about', { title: 'Custom Title' });
// Custom title building
RouterConfiguration.customize({
buildTitle(transition) {
const titles = transition.routeTree.root.children.map(c => c.title);
return `${titles.join(' - ')} | My App`;
}
})Setting titles → | Customizing titles →
How do I generate URLs without navigating?
import { IRouter } from '@aurelia/router';
import { resolve } from '@aurelia/kernel';
const router = resolve(IRouter);
// Generate path
const userPath = await router.generatePath({
component: 'users',
params: { id: 42 }
});
// Result: "/users/42"
// Use in template
<a href.bind="userPath">View User</a>How do I work with base paths (multi-tenant apps)?
RouterConfiguration.customize({
basePath: '/tenant1/app' // All routes will be prefixed
})<base href="/tenant1/app">How do I handle browser back/forward buttons?
// The router handles this automatically with historyStrategy
// To control history behavior per navigation:
router.load('page', {
historyStrategy: 'replace' // Don't create history entry
});
router.load('page', {
historyStrategy: 'push' // Create history entry (default)
});How do I access the current route information?
import { ICurrentRoute } from '@aurelia/router';
import { resolve } from '@aurelia/kernel';
export class MyComponent {
private readonly currentRoute = resolve(ICurrentRoute);
attached() {
console.log('Current path:', this.currentRoute.path);
console.log('Parameters:', this.currentRoute.parameterInformation);
}
}Troubleshooting
My routes don't work with clean URLs (no hash)
Problem: Getting 404 errors when refreshing or accessing routes directly
Solution:
Ensure
<base href="/">is in your HTMLConfigure server for SPA routing (return index.html for all routes)
Or use hash routing:
useUrlFragmentHash: true
External links are triggering the router (rare)
Problem: External links somehow being handled by router
This should NOT happen - the router automatically ignores external links like https://, mailto:, tel:, etc.
If it's happening:
Check your link format - is it truly external?
You probably don't need the
externalattribute anymoreLinks with protocol (
https://,mailto:) are automatically bypassed
Only needed for edge cases:
<!-- Internal-looking URLs that should bypass router -->
<a href="/api/download" external>API endpoint</a>
<a href="/static/old-page.html" external>Legacy page</a>Navigation isn't working from nested components
Problem: Links to sibling routes not working
Solution: Use ../ prefix for parent context
<a href="../sibling">Sibling Route</a>My lifecycle hooks aren't being called
Problem: canLoad, loading, etc. not executing
Solution: Implement the IRouteViewModel interface
import { IRouteViewModel } from '@aurelia/router';
export class MyComponent implements IRouteViewModel {
canLoad(params: Params) { /* ... */ }
}Route parameters aren't updating when navigating between same routes
Problem: Navigating from /users/1 to /users/2 doesn't update component
Solution: Configure transition plan
{
path: 'users/:id',
component: UserDetail,
transitionPlan: 'invoke-lifecycles' // Re-invoke hooks
}How do I debug routing issues?
import { IRouterEvents } from '@aurelia/router';
import { resolve } from '@aurelia/kernel';
export class MyApp {
constructor() {
const events = resolve(IRouterEvents);
events.subscribe('au:router:navigation-start', (evt) => {
console.log('Navigation started:', evt);
});
events.subscribe('au:router:navigation-end', (evt) => {
console.log('Navigation ended:', evt);
});
events.subscribe('au:router:navigation-error', (evt) => {
console.error('Navigation error:', evt);
});
}
}Complete Documentation
Last updated
Was this helpful?