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
        • 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
      • 0001 to 0023
      • 0088 to 0723
      • 0901 to 0908
    • 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
  • Create a navigation menu using a navigation model
  • Using the isActive property
  • Excluding routes from the navigation model
  • Disabling navigation model
  • Combining ICurrentRoute with the navigation model

Was this helpful?

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

Navigation model

Create a navigation menu using navigation model in Router-Lite.

PreviousRouter eventsNextTransition plan

Last updated 2 months ago

Was this helpful?

The navigation model can be thought of as view-friendly version of the configured routes. It provides similar information as of the configured routes with some additional data to it. This is typically useful when you want to create navigation menu from the already registered/configured routes in the router, without necessarily duplicating the data. The information takes the following shape.

interface INavigationModel {
  /**
   * Collection of routes.
   */
  readonly routes: readonly {
    readonly id: string;
    readonly path: string[];
    readonly redirectTo: string | null;
    readonly title: string | ((node: RouteNode) => string | null) | null;
    readonly data: Record<string, unknown>;
    readonly isActive: boolean;
  }[];
}

Note that apart from , all other properties of the route object are same as the corresponding configured route.

This section provides example of how to use navigation model while discussing different aspects of it.

Create a navigation menu using a navigation model

The following example shows how to create a navigation menu using the info from the navigation model.

In this example, we are using a custom element named nav-bar. In the custom element we inject an instance of IRouteContext and we grab the navigation model from the routing context.

import { resolve } from 'aurelia';
import { INavigationModel, IRouteContext } from '@aurelia/router-lite';

export class NavBar {
  private readonly navModel: INavigationModel = resolve(IRouteContext).navigationModel;

  public async binding() {
    await this.navModel.resolve()
  }
}

Then the information from the model is used in the view to create the navigation menu.

<nav style="display: flex; gap: 0.5rem;">
    <template repeat.for="route of navModel.routes">
        <a href.bind="route.path | firstNonEmpty">\${route.title}</a>
    </template>
</nav>

It additionally shows that from the NavBar#binding, INavigationModel#resolve() is awaited. This is recommended, when dealing with async route configuration. This allows all the promises to be resolved and thereafter building the navigation information correctly.

Note that in the example above we aren't dealing with async routing. Therefore, for that example waiting the INavigationModel#resolve() can be avoided.

In case you want to inject the IRouteContext in the app-root, you need to use a lazy injection, for example: routeContext = resolve(lazy(IRouteContext)). An eager injection does not work for app-root due to the timing of app root and the root route-context creation.

Using the isActive property

The isActive property is true when this route is currently active (loaded), and otherwise it is false. A typical use-case for this property is to apply or remove the "active" style to the links, depending on if the link is active or not. You can see this in the following example where a new .active class is added and that is bound to the isActive property.

<style>
  .active {
    font-weight: bold;
  }
</style>
<nav>
  <template repeat.for="route of navModel.routes">
    <a href.bind="route.path | firstNonEmpty" active.class="route.isActive">${route.title}</a>
  </template>
</nav>

You can see this in action below.

Excluding routes from the navigation model

By default, all configured routes are added to the navigation model. However, there might be routes which is desired to be excluded from the navigation model; for example: a fallback route for un-configured routes. To this end, a route can be configured with nav: false to instruct the router not to included it in the navigation model.

import { route } from '@aurelia/router-lite';
import { Home } from './home';
import { About } from './about';
import { NotFound } from './not-found';

@route({
  routes: [
    {
      path: ['', 'home'],
      component: Home,
      title: 'Home',
    },
    {
      path: 'about',
      component: About,
      title: 'About',
    },
    {
      path: 'notfound',
      component: NotFound,
      title: 'Not found',
      nav: false,       // <-- exclude from navigation model
    },
  ],
  fallback: 'notfound',
})
export class MyApp {}

You see this in action in the example below.

Disabling navigation model

Combining ICurrentRoute with the navigation model

While the navigation model provides information about all configured routes, sometimes you also need the exact active route or query parameters. The ICurrentRoute object can be injected in tandem with your navigation model:

import { IRouteContext, INavigationModel, ICurrentRoute } from '@aurelia/router-lite';
import { resolve } from '@aurelia/kernel';

export class NavBar {
  // same as regular usage of navigation model
  private readonly navModel: INavigationModel = resolve(IRouteContext).navigationModel;
  private readonly currentRoute = resolve(ICurrentRoute);

  public async binding() {
    await this.navModel.resolve();
    console.log('Active segment:', this.currentRoute.path);
    console.log('Active query:', this.currentRoute.url.split('?')[1]);
  }
}

Using both navModel and currentRoute, you can dynamically highlight the active route in your navigation menu, differentiate query-only changes, and so on.

If you are not creating a menu using the navigation model, you can also deactivate the navigation model by setting false to the useNavigationModel . Doing so, will set the IRouteContext#navigationModel to null and skip further processing.

router option
isActive
Logorouter-lite - navigation-model - StackBlitzStackBlitz
Logorouter-lite - navigation-model - isactive - StackBlitzStackBlitz
Logorouter-lite - navigation-model - exclusion - StackBlitzStackBlitz