LogoLogo
HomeDiscourseBlogDiscord
  • Introduction
  • Introduction
    • Quick start
    • Aurelia for new developers
    • Hello world
      • Creating your first app
      • Your first component - part 1: the view model
      • Your first component - part 2: the view
      • Running our app
      • Next steps
  • Templates
    • Template Syntax
      • Attribute binding
      • Event binding
      • Text interpolation
      • Template promises
      • Template references
      • Template variables
      • Globals
    • Custom attributes
    • Value converters (pipes)
    • Binding behaviors
    • Form Inputs
    • CSS classes and styling
    • Conditional Rendering
    • List Rendering
    • Lambda Expressions
    • Local templates (inline templates)
    • SVG
  • Components
    • Component basics
    • Component lifecycles
    • Bindable properties
    • Styling components
    • Slotted content
    • Scope and context
    • CustomElement API
    • Template compilation
      • processContent
      • Extending templating syntax
      • Modifying template parsing with AttributePattern
      • Extending binding language
      • Using the template compiler
      • Attribute mapping
  • Getting to know Aurelia
    • Routing
      • @aurelia/router
        • Getting Started
        • Creating Routes
        • Routing Lifecycle
        • Viewports
        • Navigating
        • Route hooks
        • Router animation
        • Route Events
        • Router Tutorial
        • Router Recipes
      • @aurelia/router-lite
        • Getting started
        • Router configuration
        • Configuring routes
        • Viewports
        • Navigating
        • Lifecycle hooks
        • Router hooks
        • Router events
        • Navigation model
        • Current route
        • Transition plan
    • App configuration and startup
    • Enhance
    • Template controllers
    • Understanding synchronous binding
    • Dynamic composition
    • Portalling elements
    • Observation
      • Observing property changes with @observable
      • Effect observation
      • HTML observation
      • Using observerLocator
    • Watching data
    • Dependency injection (DI)
    • App Tasks
    • Task Queue
    • Event Aggregator
  • Developer Guides
    • Animation
    • Testing
      • Overview
      • Testing attributes
      • Testing components
      • Testing value converters
      • Working with the fluent API
      • Stubs, mocks & spies
    • Logging
    • Building plugins
    • Web Components
    • UI virtualization
    • Errors
      • Kernel Errors
      • Template Compiler Errors
      • Dialog Errors
      • Runtime HTML Errors
    • Bundlers
    • Recipes
      • Apollo GraphQL integration
      • Auth0 integration
      • Containerizing Aurelia apps with Docker
      • Cordova/Phonegap integration
      • CSS-in-JS with Emotion
      • DOM style injection
      • Firebase integration
      • Markdown integration
      • Multi root
      • Progress Web Apps (PWA's)
      • Securing an app
      • SignalR integration
      • Strongly-typed templates
      • TailwindCSS integration
      • WebSockets Integration
      • Web Workers Integration
    • Playground
      • Binding & Templating
      • Custom Attributes
        • Binding to Element Size
      • Integration
        • Microsoft FAST
        • Ionic
    • Migrating to Aurelia 2
      • For plugin authors
      • Side-by-side comparison
    • Cheat Sheet
  • Aurelia Packages
    • Validation
      • Validation Tutorial
      • Plugin Configuration
      • Defining & Customizing Rules
      • Architecture
      • Tagging Rules
      • Model Based Validation
      • Validation Controller
      • Validate Binding Behavior
      • Displaying Errors
      • I18n Internationalization
      • Migration Guide & Breaking Changes
    • i18n Internationalization
    • Fetch Client
      • Overview
      • Setup and Configuration
      • Response types
      • Working with forms
      • Intercepting responses & requests
      • Advanced
    • Event Aggregator
    • State
    • Store
      • Configuration and Setup
      • Middleware
    • Dialog
  • Tutorials
    • Building a ChatGPT inspired app
    • Building a realtime cryptocurrency price tracker
    • Building a todo application
    • Building a weather application
    • Building a widget-based dashboard
    • React inside Aurelia
    • Svelte inside Aurelia
    • Synthetic view
    • Vue inside Aurelia
  • Community Contribution
    • Joining the community
    • Code of conduct
    • Contributor guide
    • Building and testing aurelia
    • Writing documentation
    • Translating documentation
Powered by GitBook
On this page
  • Emitted events
  • Subscribing to the events
  • Current route

Was this helpful?

Export as PDF
  1. Getting to know Aurelia
  2. Routing
  3. @aurelia/router-lite

Router events

Learn about how to subscribe to and handle router events.

PreviousRouter hooksNextNavigation model

Last updated 10 days ago

Was this helpful?

You can use the lifecycle hooks ( and ) to intercept different stages of the navigation when you are working with the routed components directly. However, if you want to tap into different navigation phases from a non-routed component, such as standalone service or a simple custom element, then you need to leverage router events. This section discusses that.

Emitted events

The router emits the following events.

  • au:router:location-change: Emitted when the browser location is changed via the and events.

  • au:router:navigation-start: Emitted by router before executing a routing instruction; or in other words, before performing navigation.

  • au:router:navigation-end: Emitted when the navigation is completed successfully.

  • au:router:navigation-cancel: Emitted when the navigation is cancelled via a non-true return value from canLoad or canUnload lifecycle hooks.

  • au:router:navigation-error: Emitted when the navigation is erred.

Subscribing to the events

The events can be subscribed to using the . However, there is another type-safe alternative to that.

To this end, inject the IRouterEvents and use the IRouterEvents#subscribe.

import {
  IRouterEvents,
  LocationChangeEvent,
  NavigationStartEvent,
  NavigationEndEvent,
  NavigationCancelEvent,
  NavigationErrorEvent,
} from '@aurelia/router-lite';
import { IDisposable, resolve } from 'aurelia';

export class SomeService implements IDisposable {
  private readonly subscriptions: IDisposable[];
  public log: string[] = [];
  public constructor() {
    const events = resolve(IRouterEvents);
    this.subscriptions = [
      events.subscribe('au:router:location-change',   (event: LocationChangeEvent)   => { /* handle event */ }),
      events.subscribe('au:router:navigation-start',  (event: NavigationStartEvent)  => { /* handle event */ }),
      events.subscribe('au:router:navigation-end',    (event: NavigationEndEvent)    => { /* handle event */ }),
      events.subscribe('au:router:navigation-cancel', (event: NavigationCancelEvent) => { /* handle event */ }),
      events.subscribe('au:router:navigation-error',  (event: NavigationErrorEvent)  => { /* handle event */ }),
    ];
  }
  public dispose(): void {
    const subscriptions = this.subscriptions;
    this.subscriptions.length = 0;
    const len = subscriptions.length;
    for (let i = 0; i < len; i++) {
      subscriptions[i].dispose();
    }
  }
}

Note that the event-data for every event has a different type. When you are using TypeScript, using IRouterEvents correctly types the event-data to the corresponding event type and naturally provides you with intellisense. This type information won't be available if you subscribe to the events using the event aggregator.

The following example demonstrates the usage of router events, where the root component displays a spinner at the start of navigation, and removes it when the navigation ends.

import { resolve } from 'aurelia';
import { IRouterEvents } from '@aurelia/router-lite';

export class MyApp {
  private navigating: boolean = false;
  public constructor() {
    const events = resolve(IRouterEvents);
    events.subscribe(
      'au:router:navigation-start',
      () => (this.navigating = true)
    );
    events.subscribe(
      'au:router:navigation-end',
      () => (this.navigating = false)
    );
  }
}

This is shown in action below.

Current route

Sometimes, you only need the information about the current route. In that case, you can surely subscribe to the au:router:navigation-end event and get the current route from the event data. For the ease of use, there is a ICurrentRoute exposed from router-lite that does exactly the same. You can directly inject it to your class to use it and avoid the boilerplate code altogether. Below is an example of how you can use it.

import { resolve } from 'aurelia';
import { ICurrentRoute } from '@aurelia/router-lite';

export class MyApp {
  private readonly currentRoute: ICurrentRoute = resolve(ICurrentRoute);

  public attached(): void {
    console.log(`path: ${this.currentRoute.path}`);
    console.log(`url: ${this.currentRoute.url}`);
    console.log(`title: ${this.currentRoute.title}`);
    console.log(`query: ${this.currentRoute.query}`);

    for (const pi of this.currentRoute.parameterInformation) {
      this.logParameterInstruction(pi);
    }
  }

  private logParameterInstruction(pi: IParameterInstruction): void {
    console.log(`config: ${pi.config.id}`);
    console.log(`viewport: ${pi.viewport}`);
    console.log(`params:`, pi.params);
    pi.children.forEach((c) => this.logParameterInstruction(c));
  }
}

See for a deeper look at the service.

instance
shared
popstate
hashchange
event aggregator
Current route
router-lite - events - StackBlitzStackBlitz
Logo