Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Please note that in Aurelia2 there are two routers, namely @aurelia/router
and @aurelia/router-lite
(this one). The router-lite one is smaller in size, supports only configured routing, and does not support direct routing, as facilitated by @aurelia/router
. Choose your router depending on your need.
Routing with Aurelia feels like a natural part of the framework. It can easily be implemented into your applications in a way that feels familiar if you have worked with other frameworks and library routers. Here is a basic example of routing in an Aurelia application using router-lite
.
The following getting started guide assumes you have an Aurelia application already created. If not, consult our Quick Start to get Aurelia installed in minutes.
router-lite
To use the router-lite
, we have to register it with Aurelia. We do this at the bootstrapping phase.
To know more about the different configuration options for router-lite, please refer the documentation on that topic.
For this example, we have a root component which is MyApp
. And then we are going to define two routes for the root component, namely home
and about
.
Let us define these components first.
With the routable components in place, let's define the routes. To this end, we need to add the route configurations to our root component MyApp
.
There are couple of stuffs to note here. We start by looking at the configurations defined using the @route
decorator where we list out the routes under the routes
property in the configuration object in the @route
decorator. The most important things in every route configurations are the path
and the component
properties. This instructs the router to use the defined component
in the viewport when it sees the associated path
.
To know more about configuring routes, please refer to the respective documentation.
The viewport is specified in the view (see my-app.html
) by using the <au-viewport>
custom element. For example, the router will use this element to display the Home
component when it sees the /
(the empty path) or the /home
paths.
The nav>a
elements are added to navigate from one view to another.
See this in action:
If you have opened the demo then you can notice that the URL in the address bar or the URLs in the nav>a
elements contains a #
(example: /#home
, /#about
etc.). Depending on your project need and esthetics you may want to get rid of the #
-character. To this end, you need set the useUrlFragmentHash
to false
, which is also the default.
For the documentation of router-lite, many live examples are prepared. It is recommended to use the live examples as you read along the documentation. However, if you are feeling adventurous enough to explore the features by yourself, here is the complete collection of the live examples at your disposal.
The examples are created using StackBlitz. Sometimes, you need to open the examples in a new tab to see changes in the URL, title etc. To this end, copy the URL appearing on the address bar on the right pane and open that in a new tab.
Create a navigation menu using navigation model in Router-Lite.
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.
Note that apart from isActive
, 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.
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.
Then the information from the model is used in the view to create the navigation menu.
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.
isActive
propertyThe 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.
You can see this in action below.
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.
You see this in action in the example below.
If you are not creating a menu using the navigation model, you can also deactivate the navigation model by setting false
to the useNavigationModel
router option. Doing so, will set the IRouteContext#navigationModel
to null
and skip further processing.
Learn about configuring the Router-Lite.
The router allows you to configure how it interprets and handles routing in your Aurelia applications. The customize
method on the RouterConfiguration
object can be used to configure router settings.
useUrlFragmentHash
If you do not provide any configuration value, the default is pushState routing. If you prefer hash-based routing to be used, you can enable this like so:
By calling the customize
method, you can supply a configuration object containing the property useUrlFragmentHash
and supplying a boolean value. If you supply true
this will enable hash mode. The default is false
.
PushState requires server-side support. This configuration is different depending on your server setup. For example, if you are using Webpack DevServer, you'll want to set the devServer.historyApiFallback
option to true
. If you are using ASP.NET Core, you'll want to call routes.MapSpaFallbackRoute
in your startup code. See your preferred server technology's documentation for more information on how to allow 404s to be handled on the client with push state.
basePath
Run the following example to understand how the value defined in base#href
is affecting the URLs.
When you open the example in a new browser tab, you can note that the URL in the address bar looks the HOSTING_PREFIX/app/home
or HOSTING_PREFIX/app/about
. This is also true for the href
values in the a
tags. This happens because <base href="/app">
is used in the index.ejs
(producing the index.html). In this case, the router-lite
is picking up the baseURI
information and performing the routing accordingly.
This needs bit more work when you are supporting multi-tenancy for your app. In this case, you might want the URLs look like https://example.com/tenant-foo/app1/view42
or https://example.com/tenant-bar/app2/view21
. You cannot set the document.baseURI
every time you start the app for a different tenant, as that value is static and readonly, read from the base#href
value.
With router-lite
you can support this by setting the basePath
value differently for each tenant, while customizing the router configuration, at bootstrapping phase. Following is an example that implements the aforementioned URL convention. To better understand, open the the example in a new tab and check the URL in address bar when you switch tenants as well as the links in the a
tags.
The actual configuration takes place in the main.ts
while customizing the router configuration in the following lines of code.
There are also the following links, included in the my-app.html
, to simulate tenant switch/selection.
With this route configuration in place, when we navigate to /home
, the default-built title will be Home | Aurelia
. We can use the following buildTitle
function that will cause the title to be Aurelia - Home
when users navigate to /
or /home
route.
Check out the following live example. You might need to open the demo in a new tab to observe the title changes.
Translating the title
As data
is an object of type Record<string, unknown>
, you are free to chose the property names inside the data
object. Here we are using the i18n
property to store the i18n key for individual routes.
In the next step we make use of the buildTitle
customization as well as a AppTask
hook to subscribe to the locale change event.
This customization in conjunction with the previously shown routing configuration will cause the title to be Aurelia - Startseite
when user is navigated to /
or /home
route and the current locale is de
. Here we are assuming that the i18n resource for the de
locale contains the following.
The following example demonstrate the title translation.
href
custom attribute using useHref
By default, the router will allow you to use both href
as well as load
for specifying routes. Where this can get you into trouble is external links, mailto:
links and other types of links that do not route. A simple example looks like this:
This seemingly innocent and common scenario by default will trigger the router and will cause an error.
Or, you can set useHref
to false
(default is true
) and only ever use the load
attribute for routes.
Using the historyStrategy
configuration option it can be instructed, how the router-lite should interact with the browser history object. This configuration option can take the following values: push
, replace
, and none
.
push
This is the default strategy. In this mode, the router-lite will interact with Browser history to push
a new navigation state each time a new navigation is performed. This enables the end users to use the back and forward buttons of the browser to navigate back and forth in an application using the router-lite.
Check out the following example to see this in action.
The main configuration can be found in the main.ts
.
To demonstrate the push
behavior, there is a small piece of code in the my-app.ts
that listens to router events to create informative text (the history
property in the class) from the browser history object that is used in the view to display the information.
As you click the Home
and About
links in the example, you can see that the new states are being pushed to the history, and thereby increasing the length of the history.
replace
This can be used to replace the current state in the history. Check out the following example to see this in action. Note that the following example is identical with the previous example, with the difference of using the replace
-value as the history strategy.
As you interact with this example, you can see that new states are replacing old states, and therefore, unlike the previous example, you don't observe any change in the length of the history.
none
Use this if you don't want the router-lite to interact with the history at all. Check out the following example to see this in action. Note that the following example is identical with the previous example, with the difference of using the none
-value as the history strategy.
As you interact with this example, you can see that there is absolutely no change in the history information, indicating non-interaction with the history object.
If you are working with pushState routing, you will need a <base>
element with href
attribute (for more information, refer ) in the head of your document. The scaffolded application from the CLI includes this in the index.html
file, but if you're starting from scratch or building within an existing application you need to be aware of this.
Configuring a base path is useful in many real-life scenarios. One such example is when you are hosting multiple smaller application under a single hosting service. In this case, you probably want the URLs to look like https://example.com/app1/view42
or https://example.com/app2/view21
. In such cases, it is useful to specify a different value for every app.
Note the a
tags with . Note that when you switch to a tenant, the links in the a
tags also now includes the tenant name; for example when we switch to tenant 'foo' the 'Home' link is changed to /foo/app/home
from /app/home
.
A buildTitle
function can be used to customize the . For this example, we assume that we have the configured the routes as follows:
When localizing your app, you would also like to translate the title. Note that the router does not facilitate the translation by itself. However, there are enough hooks that can be leveraged to translate the title. To this end, we would use the in the route configuration to store the i18n key.
You have two options when it comes to working with external links. You can specify the link as external using the .
You can use the to override the configured history strategy for individual routing instructions.
Using the activeClass
option you can add a class name to the router configuration. This class name is used by the when the associated instruction is active. The default value for this option is null
, which also means that the load
custom attribute won't add any class proactively. Note that the router-lite does not define any CSS class out-of-the-box. If you want to use this feature, make sure that you defines the class as well in your stylesheet.
Learn how Router-Lite handles the re-entrance of the same component and how to override the default behavior.
The transition plan in router-lite is meant for deciding how to process a navigation instruction that intends to load the same component that is currently loaded/active, but with different parameters. As the router-lite uses a sensible default based on the user-voice, probably you never need to touch this area. However, it is still good to know how to change those defaults, whenever you are in need to do that (and we all know that such needs will arise from time to time).
Transition plan can be configured using the transitionPlan
property in the routing configuration. The allowed values are replace
, invoke-lifecycles
, none
or a function that returns one of these values.
replace
: This instructs the router to completely remove the current component and create a new one, behaving as if the component is changed. This is the default behavior if the parameters are changed.
invoke-lifecycles
: This instructs the router to call the lifecycle hooks (canUnload
, canLoad
, unloading
and loading
) of the component.
none
: Does nothing. This is the default behavior, when nothing is changed.
The child routes inherits the transitionPlan
from the parent.
When the transitionPlan
property in the routing configuration is not configured, router-lite uses replace
when the parameters are changed and none
otherwise.
It might be normal to think that the default selection of the replace
transition plan when the parameter changes, to be an overkill and the default selection should have been invoke-lifecycles
instead. As a matter of fact that's the default option in Aurelia1 as well as in earlier versions of Aurelia2. However, as understood from the user-voices that replace
would in this case cause less surprises. Hence the default behavior is changed to replace
.
Transition plans defined on the root are inherited by the children. The example below shows that the transitionPlan
on the root is configured to replace
and this transition plan is inherited by the child route configuration. This means that every time the link is clicked, the component is created new and the view reflects that as well.
See this example in action below.
You can use a function to dynamically select transition plan based on route nodes. The following example shows that, where for every components, apart from the root component, invoke-lifecycles
transition plan is selected.
The behavior can be validated by alternatively clicking the links multiple times and observing that the CeOne#id2
increases, whereas CeOne#id1
remains constant. This shows that every attempt to load the CeOne
only invokes the lifecycle hooks without re-instantiating the component every time. You can try out this example below.
This can be interesting when dealing with sibling viewports, as you can select different transition plan for different siblings.
The example above selects invoke-lifecycles
for the CeTwo
and replace
for everything else. When you alternatively click the links multiple times, you can see that CeOne
is re-instantiated every time whereas for CeTwo
only the lifecycles hooks are invoked and the instance is reused. You can see the example in action below.
Learn about the different routing hooks and how to leverage those in terms of dis/allow loading or unloading as well as performing setup and teardown of a view.
Inside your routable components which implement the IRouteViewModel
interface, there are certain methods that are called at different points of the routing lifecycle. These lifecycle hooks allow you to run code inside of your components such as fetch data or change the UI itself.
Router lifecycle hook methods are all completely optional. You only have to implement the methods you require. The router will only call a method if it has been specified inside of your routable component. All lifecycle hook methods also support returning a promise and can be asynchronous.
If you are working with components you are rendering, implementing IRouteViewModel
will ensure that your code editor provides you with intellisense to make working with these lifecycle hooks in the appropriate way a lot easier.
Using the canLoad
and canUnload
hooks you can determine whether to allow or disallow navigation to and from a route respectively. The loading
and unloading
hooks are meant to be used for performing setup and clean up activities respectively for a view. Note that all of these hooks can return a promise, which will be awaited by the router-lite pipeline. These hooks are discussed in details in the following section.
In case you are looking for the global/shared routing hooks, there is a separate documentation section dedicated for that.
canLoad
The canLoad
method is called upon attempting to load the component. It allows you to determine if the component should be loaded or not. If your component relies on some precondition being fulfilled before being allowed to render, this is the method you would use.
The component would be loaded if true
(it has to be boolean
true
) is returned from this method. To disallow loading the component you can return false
. You can also return a navigation instruction to navigate the user to a different view. These are discussed in the following sections.
Returning any value other than boolean true
, from within the canLoad
function will cancel the router navigation.
The following example shows that a parameterized route, such as /c1/:id?
, can only be loaded if the value of id
is an even number. Note that the value of the id
parameter can be grabbed from the the first argument (params
) to the canLoad
method.
You can also see this example in action below.
canLoad
Not only can we allow or disallow the component to be loaded, but we can also redirect. The simplest way is to return a string path from canLoad
. In the following example, we re-write the previous example, but instead of returning false
, we return a path, where the user will be redirected.
You can also see this example in action below.
If you prefer a more structured navigation instructions then you can also do so. Following is the same example using route-id and parameters object.
Note that you can also choose to return a sibling navigation instructions. This can be done by returning an array of navigation instructions.
You can also see the example in action below.
Apart from accessing the route parameter, the query and the fragment associated with the URL can also be accessed inside the canLoad
hook. To this end, you can use the second argument (next
) to this method.
The following example shows that id
query parameter is checked whether that is an even number or not. If that condition does not hold, then user is redirected to a different view with the query and fragment.
You can also see the example in action below.
loading
The loading
method is called when your component is navigated to. If your route has any parameters supplied, they will be provided to the loading
method as an object with one or more parameters as the first argument.
In many ways, the loading
method is the same as canLoad
with the exception that loading
cannot prevent the component from loading. Where canLoad
can be used to redirect users away from the component, the loading
method cannot.
This lifecycle hook can be utilized to perform setup; for example, fetching data from backend API etc.
All of the above code examples for canLoad
can be used with load
and will work the same with the exception of being able to return true
or false
boolean values to prevent the component being loaded.
One of the examples is refactored using loading
hook that is shown below.
Following is an additional example, that shows that you can use the next.title
property to dynamically set the route title from the loading
hook.
canUnload
The canUnload
method is called when a user attempts to leave a routed view. The first argument (next
) of this hook is a RouteNode
which provides information about the next route.
This hook is like the canLoad
method but inverse. You can return a boolean true
from this method, allowing the router-lite to navigate away from the current component. Returning any other value from this method will disallow the router-lite to unload this component.
Returning any value other than boolean true
, from within the canUnload
function will cancel the router navigation.
The following example shows that before navigating away, the user is shown a confirmation prompt. If the user agrees to navigate way, then the navigation is performed. The navigation is cancelled, if the user does not confirm.
You can see this example in action below.
unloading
The unloading
hook is called when the user navigates away from the current component. The first argument (next
) of this hook is a RouteNode
which provides information about the next route.
This hook is like the loading
method but inverse.
The following example shows that a unloading
hook logs the event of unloading the component.
This can also be seen in the live example below.
For completeness it needs to be noted that the canLoad
hook is invoked before loading
and canUnload
hook is invoked before unloading
. In the context of swapping two views/components it is as follows.
canUnload
hook (when present) of the current component is invoked.
canLoad
hook (when present) of the next component (assuming that the canUnload
returned true
) is invoked.
unloading
hook (when present) of the current component is invoked.
loading
hook (when present) of the current component is invoked.
Note that the last 2 steps may run in parallel, if the hooks are asynchronous.
How to implement router "guards" into your applications to protect routes from direct access.
Router hooks are pieces of code that can be invoked at the different stages of routing lifecycle. In that sense, these hooks are similar to the lifecycle hooks of the routed view models. The difference is that these hooks are shared among multiple routed view models. Therefore, even though the hook signatures are similar to that of the lifecycle hooks, these hooks are supplied with an additional argument that is the view model instance.
If you worked with Aurelia 1, you might know these by their previous name: router pipelines.
Shared lifecycle hook logic can be defined by implementing one of the router lifecycle hooks (canLoad
, loading
etc.) on a class with the @lifecycleHooks()
decorator. This hook will be invoked for each component where this class is available as a dependency.
While the router hooks are indeed independent of the components you are routing to, the functions are basically the same as you would use inside of an ordinary component.
This is the contract for ordinary route lifecycle hooks for components:
And the following is the contract for shared lifecycle hooks.
The only difference is the addition of the first viewModel
parameter. This comes in handy when you need the component instance since the this
keyword won't give you access to the component instance like it would in ordinary instance hooks.
Before starting with the involved details of the shared/global lifecycle hooks, let us first create an example lifecycle hook. To this end, we consider the typical use-case of authorization; that is restricting certain routes to users with certain permission claims.
The example we are going to build in this section is just a toy example. For your production code, perform due diligence to evaluate the potential security threats.
For this example, we will create two lifecycle hooks; one for authentication and another is for authorization. However, before directly dive into that, let us briefly visit, how the routes are configured.
Note that the data
property of the route configuration option is used here to define the routes' permission claim. This is used by the auth hooks later to determine whether to allow or disallow the navigation. With that we are now ready to discuss the hooks.
The first hook will check if the current route is protected by a claim and there is a currently logged in user. When there is no logged in user, it performs a redirect to login page. This is shown below.
The second hook will check if the current user has the permission claims to access the route. Where the user does not satisfies the claims requirements the user is redirected to a forbidden page. This is shown below.
Lastly, we need to register these two hooks to the DI container to bring those into action.
Note that the authentication hook is registered before the authorization hook. This ensures that the authentication hook is invoked before than the authorization hook which is also semantically sensible.
To know more about the order of invocation, please refer the respective section.
And that's the crux of it. You can see this example in action below.
Note that even though in the example we limit the the hooks to only canLoad
method, more than one lifecycle methods/hooks can also be leveraged in a shared lifecycle hook (a class decorated by the @lifecycleHooks()
decorator).
The lifecycle hooks can be registered either globally (as it is done in the previous example or as local dependencies.
The globally registered lifecycle hooks are invoked for every components. Thus, it is recommended to use those sparsely. On the other hand, when a hook is registered as a dependency of a particular component, it is invoked only for that one component.
This is shown in the example below, where there are two globally registered hooks, which are invoked for every components.
Note that the globally registered hooks in the example above do nothing significant other than logging the invocations. This is shown below.
The log entries are then enumerated on the view. The following is one such example of log entries.
You may get a different log depending on your test run. However, it can still be clearly observed that both hook1
and hook2
are invoked for every components. Depending on your use-case, that might not be optimal.
To achieve a granular control on the lifecycle hooks, you can register the hooks as the dependencies
for individual routed view models. This ensures that the lifecycle hooks are invoked only for the components where those are registered as dependencies. This shown in the example below where there are three hooks, and one component has two hooks registered as dependencies
and another component has only hook registered.
When ChildOne
or ChildTwo
is loaded or unloaded you can observe that only Hook2
is invoked for ChildTwo
, whereas both Hook1
and Hook2
are invoked for ChildOne
. Below is an example log from one of such test runs.
You can see the example in action below.
You can of course choose to use both kind of registrations. The following example shows that Hook3
is registered globally and therefore is invoked for every components whereas Hook1
is only invoked for ChildOne
and Hook2
is only invoked for ChildTwo
.
When using multiple lifecycle hooks, if any hook returns a non-true
value (either a false
or a navigation instruction) from canLoad
or canUnload
, it preempts invocation of the other hooks in the routing pipeline.
This is shown in the following example. The example shows that there are two hooks, namely hook1
and hook2
. hook1
return false
if the path c1
is navigated with a non-number and non-even number; for example it denies navigation to c1/43
but allows c1/42
.
You can see the example in action below.
If you run the example and try clicking the links, you can observe that once hook1
returns false
, hook2
is not invoked. One such example log is shown below.
The thumb rule is that the hooks are invoked in the order they are registered. That is if some Hook1
is registered before Hook2
in DI then Hook1
will be invoked before the Hook2
. You can see this in the example of globally registered hooks.
That is also true, when registering hooks as one of the dependencies
for a custom element. You can see this in the example of hooks as dependencies.
When using both globally registered hooks as well as local dependencies, the global hooks are invoked before the locally registered hooks. You can see this in action in this example.
Lastly, the shared lifecycle hooks are invoked before the instance lifecycle hooks.
Learn about viewports in Router-Lite and how to configure hierarchical routing.
The <au-viewport>
element, or commonly referred to as viewport (not to confuse with viewport
meta tag), is the "outlet", where the router-lite attaches/loads the components. For a basic example of viewport, please refer the "Getting started"-tutorial. Most of the examples in the preceding sections show the usage of only a single viewport. However, you can use multiple viewports with the sibling viewports and hierarchical routing. These are useful to create different routing layouts. In the subsequent sections, we first discuss about that. Later in this part of the documentation, we focus on the different configuration options available for viewports.
As seen in the "Getting started"-tutorial, a component can define a set of children routes (using either the @route
decorator or the static properties). The child routes can also in turn define children routes of there own. Such route configuration are commonly known as hierarchical route configuration.
To understand it better, let us consider an example. We want to show a list of products, as links, and when a product link is clicked, we display the details of the product.
To this end we want a viewport on the root component which is used to host the list component. The list component itself houses anther viewport, or more accurately a child viewport, which is then used to host the product details.
The route configuration for the root component consists of a single root for the list component and it also houses a single viewport. The Products
component defines its own child route configuration and houses a child viewport. This is shown below.
The IProductService
injected to the Products
is just some service used to populate the product list and has very little relevance to the discussion related to the router. And the extra style is added to display the list and the details side by side. And that's pretty much all you need for a simple hierarchical routing configuration. You can see this in action below.
If you open the example in a new tab, you can see how the URL paths are constructed. For example, when you click a product link, the URL is /42/details
or /products/42/details
. This also means that when you try to navigate to that URL directly, the product details will be loaded from the start. It essentially creates shareable URLs.
Two viewports are called siblings if they are under one parent routing hierarchy. Let us recreate the previous example but using sibling viewports this time.
To this end, we want to viewports, housed side-by-side on the root component. We show the products' list on one viewport and the details of the selected product on the other one.
To this end, let us start with the routing configuration on the root component.
Two routes, one for the list another for the details, are configured on the route. Next we need 2 viewports to on the root component. Let us get that done.
Even though we are not yet done, you can check out our work so far in the live example below.
If you run the example, you can immediately see a "problem" that both the viewports are loading the products' list. Although it is not an error per se, with natural use-case in mind, you probably like to avoid that. Let us fix this "problem" first.
This is happening due to the default value of the default
attribute of the <au-viewport>
that is set to ''
(empty string). This default value enables loading the component associated with the empty path without any additional configuration. This default behavior makes sense as the usage of a single viewport at every routing hierarchy might be prevalent.
However, we need a way to prevent this duplication. To this end, we can bind null
to the default
attribute of a viewport, which instructs the router-lite that this particular viewport should be left out when it is empty (that is no component is targeted to be loaded in this viewport).
You can see in the live example below that this fixes the duplication issue.
We still need a way to load the product details on the second viewport. Note that till now, the two viewports cannot be referentially differentiated from one another; that is if you want to load a component specifically on the first or on the second viewport, there is no way to do this for now. To this end, we need to name the viewports.
Although we name the viewports semantically, it is not necessary, and you are free to choose viewport names, as you like. Lastly, we need to use the load
attribute in the Products
component to construct the URL, or more accurately the routing instruction correctly, such that the details of the product is loaded on the details
viewport.
Using the load
attribute we are instructing the router-lite to load the Product
(using the route-id details
) component, with the id
parameter of the route set to the id
of the current item
in the repeater, in the details
viewport. With the context.bind:null
, we are instructing the router-lite to perform this routing instruction on the root routing context (refer the documentation for the load
attribute for more details). Now, when someone clicks a product link the associated details are loaded in the details
viewport. You can see this in action below.
If you open the example in a new tab, you can see how the URL paths are constructed. For example, when you click a product link, the URL is /details/42@details+products@list
.
As seen in the sibling viewports example, viewports can be named. It is particularly useful when there are multiple sibling viewports present. Note that specifying a value for the name
attribute of viewport is optional, and the default value is simply 'default'
.
In the following example, we have the main
viewport for our main content and then another viewport called sidebar
for our sidebar content.
The names can be used to instruct the router-lite to load a specific component to a specific named viewport. To this end the path syntax is as follows:
The live example below shows this.
Note the load
attributes in the anchor
elements.
In the example, clicking the first anchor loads the products
component in the list
viewport and the details of the product with #{id
} into the details
viewport. The second anchor facilitates loading only the the details of the product with #{id
} into the details
viewport.
For more details about navigating and instructions for router-lite, please refer the documentation.
By default, the routes/components are loaded into the first available viewport, when there is no viewport instruction is present. However, the routes can also be configured, such that a configured route is allowed to be loaded only in a certain viewport. This is useful when you know that a certain component needs to be loaded in a certain viewport, because in that case you can use the simple {path}
instruction instead of the more verbose alternative, the {path}@{viewport-name}
instruction. To this end, use the viewport
option of the route configuration.
In this example, we are specifying that the Products
component needs to be loaded into the list
viewport and the Product
component need to be loaded into the details
viewport. You can also see this in the live example below.
Note the anchor
s in the example that show that the viewport names can now be dropped from the routing instructions.
used-by
The used-by
attribute on the au-viewport
component can be thought of as (almost) the parallel of the viewport
configuration option on route configuration. Using this property on a viewport, you can "reserve" a viewport for particular component(s). In other words, you are instructing the router that no other components apart from those specified can be loaded into a viewport with used-by
set.
In this example, we are instructing the router-lite to reserve the first viewport for ce-two
custom element and the reserve the second viewport for ce-one
custom element. You can see this in the live example below, by clicking the links and observing how the components are loaded into the reserved viewports.
You can reserve a viewport for more than one component. To this end, you can use comma-separated values for the used-by
attribute.
The live example below shows this in action
Although the used-by
attribute feels like a markup alternative of the viewport
configuration option on route configuration, there is a subtle difference. Having the used-by
property on a particular viewport set to X
component, does not prevent a preceding viewport without any value for the used-by
property to load the X
component. This is shown in action in the example below.
Note how clicking the links load the components also in the first viewport without any value for the used-by
.
When no route is loaded into a viewport, a 'default' route is loaded into the viewport. For every viewport, such defaults can be configured using the default
attribute. It is optional to specify a value for this attribute and the empty string (''
) is used as the default value for this property. This explains why the route with empty path (when exists) is loaded into a viewport without the default
attribute set, as seen in the sibling viewports example.
Another path can be used to override the default value of the default
attribute. The following example shows four viewports with varied values for the default
attribute. Whereas the first viewport might be the usual viewport with empty path, the other three specifies different default values. These components are loaded into the viewport, by default when the application is started.
The example below shows this in action.
Note that default
attribute can also be bound to null
, to instruct the router-lite not to load any component into ths viewport when no component is scheduled (either by explicit instruction of implicit availability check) to be loaded into the viewport. This is useful when you have more than one viewports and you want to load the empty path (assuming it is configured) in a particular viewport. In that case, you can bind null
to the default
attribute of the other viewport. To see examples of this, please refer to the sibling viewport section.
If a route cannot be recognized, a fallback route is looked for and loaded (when configured) into the viewport. Such fallback can be configured using the fallback
property of the route configuration. au-viewport
also offers a similar fallback
attribute, using which a fallback component can be configured for a particular viewport. The fallback
attribute is similar to its route configuration counterpart, with only one difference. The fallback
attribute in the au-viewport
, when configured, always takes precedence over the fallback
route configuration option. This is shown in the live example below.
A function for the value of fallback
is also supported. An example looks like as follows, where the example redirects the user to NF1
component if an attempt to load a path /foo
is made. Every other attempt to load an unknown path is results loading the NF2
component.
You can also see this in action below.
Learn about configuring routes in Router-Lite.
The router takes your routing instructions and matches the URL to one of the configured Routes to determine which components to render. To register routes you can either use the @route
decorator or you can use the static routes
property to register one or more routes in your application. This section describes the route configuration options in details.
The routing configuration syntax for router-lite is similar to that of other routers you might have worked with before. If you have worked with Express.js routing, then the syntax will be very familiar to you.
A route is an object containing a few required properties that tell the router what component to render, what URL it should match on and other route-specific configuration options.
For the example above, when the router-lite sees either the path /
or /home
, it loads the Home
component and if it sees the /about
path it loads the About
component.
Note that the example above uses the @route
decorator. In case you cannot use the decorator, you can use the static properties instead. The example shown above can be rewritten as follows.
As the re-written example shows, you can convert the properties in the options object used for the @route
decorator into static
properties in the view model class.
Apart from the static API including the @route
decorator, there is also an instance-level hook named getRouteConfig
that you can use to configure your routes. This is shown in the example below.
See this in action below.
Note that the hook is also supplied with a parent route configuration, and the new route node. These values can be nullable; for example, for root node there is no parent route configuration.
The getRouteConfig
can also be async
. This is shown in the example below.
See this in action below.
path
and parametersThe path defines one or more patterns, which are used by the router-lite to evaluate whether or not an URL matches a route or not. A path can be either a static string (empty string is also allowed, and is considered as the default route) without any additional dynamic parts in it, or it can contain parameters. The paths defined on every routing hierarchy (note that routing configurations can be hierarchical) must be unique.
Required parameters are prefixed with a colon. The following example shows how to use a required parameter in the path
.
Note that the value of the id
parameter as defined in the route configuration (:id
) is available via the params.id
. Check out the live example to see this in action.
Optional parameters start with a colon and end with a question mark. The following example shows how to use an optional parameter in the path
.
In the example, shown above, the Product
component is loaded when the router-lite sees paths like /product
or /product/some-id
, that is irrespective of a value for the id
parameter. You can see the live example below.
Note that there is an additional link added to the products.html
to fetch a random product.
As the id
parameter is optional, even without a value for the id
parameter, clicking the link loads the Product
component. Depending on whether or not there is a value present for the id
parameter, the Product
component generates a random id and loads that.
The wildcard parameters, start with an asterisk instead of a colon, act as a catch-all, capturing everything provided after it. The following example shows how to use a wildcard parameter in the path
.
In the example, shown above, the Product
component is loaded when the router-lite sees paths like /product/some-id
or /product/some-id/foo/bar
. You can see the live example below.
The example utilizes a wildcard parameter named rest
, and when the value of rest
is 'image'
, an image for the product is shown. To this end, the canLoad
hook of the Product
view-model reads the rest
parameter.
You can configure the title for the routes while you are configuring the routes. The title can be configured in the root level, as well as in the individual route level. This can be seen in the following example using the @route
decorator.
If you prefer using the static routes
property, the title can be set using a static title
property in the class. The following example has exactly the same effect as of the previous example.
Note that, instead of a string, a function can also be used for title
to lazily set the title.
By specifying the redirectTo
property on our route, we can create route aliases. These allow us to redirect to other routes. In the following example, we redirect our default route to the home
page and the about-us
to about
page.
You can see this action below.
Note that redirection also works when there are multiple paths/aliases defined for the same component.
You can see this action below.
You can use route parameters for redirectTo
. The following example shows that the parameters from the about-us
path is rearranged to the about
path.
You can see this action below.
We can instruct the router-lite to redirect the users to a different configured path, whenever it sees any unknown/un-configured paths. To this end, we can use the fallback
configuration option. Following example shows how to use this configuration option.
As the example shows, the fallback
is configured as follows.
There is a custom element, named NotFound
, which is meant to be loaded when any unknown/un-configured route is encountered. As you can see in the above example, clicking the "Foo" link that is with un-configured href
, leads to the NotFound
view.
It is recommended that you configure a fallback
at the root to handle the navigation to un-configured routes gracefully.
The name of the custom element, meant to be displayed for any un-configured route can also be used to define fallback
. The following example demonstrates this behavior, where not-found
, the name of custom element NotFound
, is used to refer the route.
An important point to note here is that when you are using the custom element name as fallback, you need to ensure that the custom element is registered to the DI container. Note that in the example above, the NotFound
component is registered to the DI container in main.ts
.
A function can be used for fallback
. The function takes the following signature.
An example can look like below, where the example redirects the user to NF1
component if an attempt to load a path /foo
is made. Every other attempt to load an unknown path is results loading the NF2
component.
You can also see this in action below.
You can also use non-string fallbacks. For example, you can use a class as the value for fallback
; such as fallback: NotFound
. Or, if you are using a function, you choose to return a class instead of returning a string. These combinations are also supported by router-lite.
Routes can be marked as case-sensitive in the configuration, allowing the navigation to the component only when the case matches exactly the configured path. See the example below where the navigation to the "about" page is only successful when the casing matches.
Thus, only an attempt to the /AbOuT
path loads the About
component; any attempt with a different casing is navigated to the fallback
. See this in action below.
There are few other routing configuration which aren't discussed above. Our assumption is that these options are more involved and might not be used that often. Moreover, to understand the utility of these options fully, knowledge of other parts of the route would be beneficial. Therefore, this section only briefly introduces these options providing links to the sections with detailed examples.
Before finishing the section on the route configuration, we need to discuss one last topic for completeness, and that is how many different ways you can configure the component
. Throughout various examples so far we have seen that components are configured by importing and using those in the routing configuration. However, there are many other ways in which the components can be configured. This section discusses those.
import()
You can see this in action below.
If you are using TypeScript, ensure that the module
property set to esnext
in your tsconfig.json
to support inline import statements.
Components can be configured using only the custom-element name of the component.
However, when configuring the route this way, you need to register the components to the DI.
You can see this configuration in action below.
Components can be configured using a function that returns a class.
You can see this configuration in action below.
Components can be configured using custom element definition.
You can see this configuration in action below.
Components can be configured using custom element instance.
You can see this configuration in action below.
Using router-lite it is also possible to use the routed view model classes directly as routes configuration. While doing so, if no paths have been explicitly configured for the components, the custom element name and aliases can be used as routing instructions. The following example demonstrates that the C1
and C2
classes are used directly as the child routes for the Root
.
The example above implies that router.load('c-1')
, or router.load('c-a')
and router.load('c-2')
, router.load('c-two')
will load the C1
and C2
respectively.
The examples discussed so far demonstrate the classic use-cases of route configurations where the parents define the child routes. Another aspect of these examples are that all the route configurations are centralized on the parent component. This section provides some examples where that configuration is distributed across different components.
We start by noting that every component can define its own path. This is shown in the following example.
The example shows that both Home
and About
uses the @route
decorator to define their own paths. This reduces the child-route configuration for MyApp
to @route({ routes: [Home, About] })
. The example can be seen in action below.
Note that other properties of route configuration can also be used in this way.
The previous example demonstrates that the Home
and About
components define the title
for themselves. The example can be seen in action below.
While adapting to distributes routing configuration, the parent can still override the configuration for its children. This makes sense, because even if a component defines its own path
, title
etc. the parent may choose to reach (route) the component via a different path or display a different title when the component is loaded. This is shown below, where the MyApp
overrides the routing configurations defined by About
.
This can be seen in action below.
You can also use the @route
decorator and the getRouteConfig
together.
This can be seen in action below.
The advantage of this kind of distributed configuration is that the routing configuration of every component is defined by every component itself, thereby encouraging encapsulation, leaving the routing configuration at the parent level to merely listing out its child components. On the other hand, highly distributed route configuration may prevent easy overview of the configured routes. That's the trade-off. Feel free to mix and match as per your need and aesthetics.
Learn about how to subscribe to and handle router events.
The router emits the following 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.
To this end, inject the IRouterEvents
and use the IRouterEvents#subscribe
.
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.
This is shown in action below.
The most usual case of defining a route configuration is by specifying the path
and the component
properties. The idea is to use the path
property to define a pattern, which when seen in the URL path, the view model defined using the component
property is activated by the router-lite. Simply put, a routing configuration is a mapping between one or more path patterns to components. Below is the simple example (from the section) of this.
Note that you can map multiple paths to a single component. Although these paths can be thought of as aliases, multiple paths, in combination with gets interesting. Another way of creating aliases is to use the configuration option.
When a given URL matches one such route, the parameter value is made available in the canLoad
, and load
.
With this configuration in place, the default-built title will be Home | Aurelia
when user is navigated to /
or /home
route. That is, the titles of the child routes precedes the base title. You can customize this default behavior by using a when customizing the router configuration.
Another way of defining the fallback
is to use the . The following example demonstrates this behavior, where the NotFound
view can be reached via multiple aliases, and instead of choosing one of these aliases the route-id
is used to refer the route.
A fallback
defined on parent is inherited by the children (to know more about hierarchical routing configuration, refer the ). However, every child can override the fallback as needed. The following example demonstrate this. The root has two and two children components can be loaded into each of those by clicking the link. Every child defines their own child routing configuration. The root defines a fallback
and one of the children overrides the fallback
by defining one of its' own. With this configuration in place, when navigation to a un-configured route ('Foo') is attempted for each children, one loads the overridden version whereas the other loads the fallback inherited from the parent (in this case the root).
id
— The unique ID for this route. The router-lite implicitly generates a id
for a given route, if an explicit value for this property is missing. Although this is not really an advanced property, due to the fact that a route can be uniquely identified with id
, it can be used in many interesting ways. For example, this can be used to generate the href
s in the view when using the or using the . Using this property is also very convenient when there are multiple aliases for a single route, and we need a unique way to refer to this route.
transitionPlan
— How to behave when the currently active component is scheduled to be loaded again in the same viewport. For more details, please refer the .
viewport
— The name of the viewport this component should be loaded into. This demands a full fledged documentation of its own. Refer to the for more details.
data
— Any custom data that should be accessible to matched components or hooks. The value of this configuration property must be an object and the object can take any shape (that is there is no pre-defined interface/class for this object). A typical use-case for the data
property is to define the permissions, required by the users, when they attempt to navigate to this route. Refer of this.
nav
- Set this flag to false
(default value is true
), to instruct the router not to add the route to the . This is typically useful to from the public navigation menu.
Components can be configured using the or dynamic import. Instead of statically importing the components, those can be imported using import()
-syntax, as the example shows below.
To know more about the router API refer .
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.
au:router:location-change
: Emitted when the browser location is changed via the and events.
The events can be subscribed to using the . However, there is another type-safe alternative to that.
Learn to navigate from one view to another using the Router-Lite. Also learn about routing context.
This section details the various ways that you can use to navigate from one part of your application to another part. For performing navigation the router-lite offers couple of alternatives, namely the href
and the load
custom attributes, and the IRouter#load
method.
href
custom attributeYou can use the href
custom attribute with an a
(anchor) tag, with a string value. When the users click this link, the router-lite performs the navigation. This can be seen in action in the live example below.
The example shows that there are two configured routes, home
and about
, and in markup there are two anchor tags that points to these routes. Clicking those links the users can navigate to the desired components, as it is expected.
You can also use the parameterized routes with the href
attribute, exactly the same way. To this end, you need to put the parameter value in the path itself and use the parameterized path in the href
attribute. This is shown in the example below.
The example shows two configured routes; one with an optional parameter. The markup has three anchor tags as follows:
The last href
attribute is an example of a parameterized route.
While configuring routes, an id
for the route can be set explicitly. This id
can also be used with the href
attribute. This is shown in the example below.
Note that the example set a route id that is different than the defined path. These route-ids are later used in the markup as the values for the href
attributes.
Note that using the route-id of a parameterized route with the href
attribute might be limiting or in some cases non-operational as with href
attribute there is no way to specify the parameters for the route separately. This case is handled by the load
attribute.
You can target named and/or sibling viewports. To this end, you can use the following syntax.
The following live example, demonstrates that.
The example shows the following variations.
Note that using the viewport name in the routing instruction is optional and when omitted, the router uses the first available viewport.
The navigation using href
attribute always happens in the current routing context; that is, the routing instruction will be successful if and only the route is configured in the current routing parent. This is shown in the example below.
In the example, the root component has two child-routes (c1
, c2
) and every child component in turn has 2 child-routes (gc11
, and gc12
and gc21
, and gc22
respectively) of their own. In this case, any href
pointing to any of the immediate child-routes (and thus configured in the current routing parent) works as expected. However, when an href
, like below (refer child1.ts
), is used to navigate from one child component to another child component, it does not work.
In such cases, the router-lite offers the following syntax to make such navigation possible.
That is, you can use ../
prefix to instruct the router to point to the parent routing context. The prefix can also be used multiple times to point to any ancestor routing context. Naturally, this does not go beyond the root routing context.
Contextually, note that the example involving route-id also demonstrates the behavior of navigating in the current context. In that example, the root component uses r1
, and r2
as route identifiers, which are the same identifiers used in the children to identify their respective child-routes. The route-ids are used in the markup with the href
attributes. Despite being the same route-ids, the navigation works because unless specified otherwise, the routing instructions are constructed under the current routing context.
href
custom attributeBy default the router-lite enables usage of the href
custom attribute, as that ensures that the router-lite handles the routing instructions by default. There might be cases, where you want to avoid that. If you want to globally deactivate the usage of href
, then you can customize the router configuration by setting false
to the useHref
configuration option.
To disable/bypass the default handling of router-lite for any particular href
attribute, you can avail couple of different ways as per your need and convenience.
Using external
or data-external
attribute on the a
tag.
Using a non-null value for the target
, other than the current window name, or _self
.
Other than that, when clicking the link if either of the alt
, ctrl
, shift
, meta
key is pressed, the router-lite ignores the routing instruction and the default handling of clicking a link takes place.
Following example demonstrate these options.
load
custom attributeAlthough the usage of href
is the most natural choice, it has some limitations. Firstly, it allows navigating in the current routing context. However, a bigger limitation might be that the href
allows usage of only string values. This might be bit sub-optimal when the routes have parameters, as in that case you need to know the order of the parameterized and static segments etc. to correctly compose the string path. In case the order of those segments are changed, it may cause undesired or unexpected results if your application.
To support structured way to constructing URL the router-lite offers another alternative namely the load
attribute. This custom attribute accepts structured routing instructions as well as string-instructions, just like the href
attribute. Before starting the discussion on the features supported exclusively by the load
attribute, let us quickly review the following example of using string-instructions with the load
attribute.
The example shows various instances of load
attribute with various string instructions.
The following sections discuss the various other ways routing instruction can be used with the load
attribute.
params
Using the bindable params
property in the load
custom attribute, you can bind the parameters for a parameterized route. The complete URL is then constructed from the given route and the parameters. Following is an example where the route-id is used with bound parameters.
The example above configures a route as follows. The route-id is then used in the markup with the bound params
, as shown in the example below.
An important thing to note here is how the URL paths are constructed for each URL. Based on the given set of parameters, a path is selected from the configured set of paths for the route, that maximizes the number of matched parameters at the same time meeting the parameter constraints.
For example, the third instance (params: {p1: 4, p3: 5}
) creates the path /c2/4/foo/?p3=5
(instance of 'c2/:p1/foo/:p2?'
path) even though there is a path with :p3
configured. This happens because the bound parameters-object is missing the p2
required parameter in the path pattern 'c2/:p1/foo/:p2/bar/:p3'
. Therefore, it constructs the path using the pattern 'c2/:p1/foo/:p2?'
instead.
In other case, the fourth instance provides a value for p2
as well as a value for p3
that results in the construction of path /c2/6/foo/7/bar/8
(instance of 'c2/:p1/foo/:p2/bar/:p3'
). This case also demonstrates the aspect of "maximization of parameter matching" while path construction.
One last point to note here is that when un-configured parameters are included in the params
object, those are converted into query string.
route
The bindable route
property in the load
attribute supports binding a class instead of route-id. The following example demonstrates the params
-example using the classes (child1
, child2
) directly, instead of using the route-id.
You can see this in action below.
Just like the href
attribute, the load
attribute also supports navigating in the current routing context by default. The following example shows this where the root component has two child-routes with r1
and r2
route-ids and the child-components in turn defines their own child-routes using the same route-ids. The load
attributes also use the route-ids as routing instruction. The routing works in this case, because the routes are searched in the same routing context.
However, this default behavior can be changed by binding the context
property of the load
custom attribute explicitly. To this end, you need to bind the instance of IRouteContext
in which you want to perform the navigation. The most straightforward way to select a parent routing context is to use the parent
property of the IRouteContext
. The current IRouteContext
can be injected using the @IRouteContext
in the class constructor. Then one can use context.parent
, context.parent?.parent
etc. to select an ancestor context.
Such ancestor context can then be used to bind the context
property of the load
attribute as follows.
The following live example demonstrate this behavior.
Note that even though the ChildOne
defines a route with r2
route-id, specifying the context
explicitly, instructs the router-lite to look for a route with r2
route-id in the parent routing context.
Using the IRouteContext#parent
path to select the root routing context is somewhat cumbersome when you intend to target the root routing context. For convenience, the router-lite supports binding null
to the context
property which instructs the router to perform the navigation in the root routing context.
This is shown in the following example.
When the route context selection involves only ancestor context, then the ../
prefix can be used when using string instruction. This also works when using the route-id. The following code snippets shows, how the previous example can be written using the ../
prefix.
active
statusWhen using the load
attribute, you can also leverage the bindable active
property which is true
whenever the associated route, bound to the href
is active. In the following example, when a link in clicked and thereby the route is activated, the active*
properties are bound from the views to true
and thereby applying the .active
-CSS-class on the a
tags.
This can also be seen in the live example below.
Note that the navigation model also offers a isActive
property.
The active
bindable can be used for other purposes, other than adding CSS classes to the element. However, if that's what you need mostly the active
property for, you may choose to configure the activeClass
property in the router configuration. When configured, the load
custom attribute will add that configured class to the element when the associated routing instruction is active.
Along with the custom attributes on the markup-side, the router-lite also offers the IRouter#load
method that can be used to perform navigation, with the complete capabilities of the JavaScript at your disposal. To this end, you have to first inject the router into your component. This can be done by using the IRouter
decorator on your component constructor method as shown in the example below.
Now you are ready to use the load
method, with many supported overloads at your disposal. These are outlined below.
The easiest way to use the load
method is to use the paths directly.
With respect to that, this method supports the string instructions supported by the href
and the load
attribute. This is also shown in the example below.
There is a major important difference regarding the context selection in the IRouter#load
method and the href
and load
custom attributes. By default, the custom attributes performs the navigation in the current routing context (refer the href
and load
attribute documentation). However, the load
method always use the root routing context to perform the navigation. This can be observed in the ChildOne
and ChildTwo
components where the load
method is used the following way to navigate from ChildOne
to ChildTwo
and vice versa. As the load
API uses the the root routing context by default, such routing instructions works. In comparison, note that with href
we needed to use the ..
prefix or with load
method we needed to set the context to null.
However, on the other hand, you need to specify the routing context, when you want to navigate inside the current routing context. The most obvious use case is when you issue routing instruction for the child-routes inside a parent component. This can also be observed in ChildOne
and ChildTwo
components where a specific context is used as part of the navigation options to navigate to the child routes.
An array of paths (string) can be used to load components into sibling viewports. The paths can be parameterized or not non-parameterized.
This is shown in the example below.
The load
method also support non-string routing instruction.
Using custom elements
You can use the custom element classes directly for which the routes have been configured. Multiple custom element classes can be used in an array to target sibling viewports.
This can be seen in action in the live example below.
Using custom element definitions
You can use the custom element definitions for which routes have been configured. Multiple definitions can be used in an array to target sibling viewports.
This can be seen in action in the live example below.
Using a function to return the view-model class
Similar to route configuration, for load
you can use a function that returns a class as routing instruction. This looks like as follows.
This can be seen in action in the live example below.
Using import()
Similar to route configuration, for load
you can use an import()
statement to import a module. This looks like as follows.
This can be seen in action in the live example below.
Note that because invoking the import()
function returns a promise, you can also use a promise directly with the load
function.
Using a viewport instruction
Any kind of routing instruction used for the load
method is converted to a viewport instruction tree. Therefore, you can also use a (partial) viewport instruction directly with the load
method. This offers maximum flexibility in terms of configuration, such as routing parameters, viewports, children etc. Following are few examples, how the viewport instruction API can be used.
This can be seen in the example below.
Along with using the routing instructions, the load
method allows you to specify different navigation options on a per-use basis. One of those, the context
, you have already seen in the examples in the previous sections. This section describes other available options.
title
The title
property allows you to modify the title as you navigate to your route. This looks like as follows.
Note that defining the title
like this, overrides the title defined via the route configuration. This can also be seen in the action below where a random title is generated every time.
titleSeparator
As the name suggests, this provides a configuration option to customize the separator for the title parts. By default router-lite uses |
(pipe) as separator. For example if the root component defines a title 'Aurelia'
and has a route /home
with title Home
, then the resulting title would be Home | Aurelia
when navigating to the route /home
. Using this option, you can customize the separator.
This can also be seen in the action below where a random title separator is selected every time.
queryParams
This option lets you specify an object to be serialized to a query string. This can be used as follows.
This can be seen in the live example below.
fragment
Like the queryParams
, using the fragment
option, you can specify the hash fragment for the new URL. This can be used as follows.
This can be seen in the live example below.
context
As by default, the load
method performs the navigation relative to root context, when navigating to child routes, the context needs to be specified. This navigation option has also already been used in various examples previously. Various types of values can be used for the context
.
The easiest is to use the custom element view model instance. If you are reading this documentation sequentially, then you already noticed this. An example looks like as follows.
Here is one of the previous example. Take a look at the child1.ts
or child2.ts
that demonstrates this.
You can also use an instance of IRouteContext
directly. One way to grab the instance of IRouteContext
is to get it inject via constructor
using the @IRouteContext
decorator. An example looks like as follows.
You can see this in action below.
Using a custom element controller instance is also supported to be used as a value for the context
option. An example looks as follows.
You can see this in action below.
And lastly, you can use the HTML element as context. Following is live example of this.
historyStrategy
Using this navigation option, you can override the configured history strategy. Let us consider the example where three routes c1
, c2
, and c3
are configured with the push
history strategy. Let us also assume that the following navigation instructions have already taken place.
After this, if we issue the following instruction,
then performing a history.back()
should load the c1
route, as the state for c2
is replaced.
transitionPlan
Using this navigation option, you can override the configured transition plan per routing instruction basis. The following example demonstrates that even though the routes are configured with a specific transition plans, using the router API, the transition plans can be overridden.
This can be seen in action below.
For completeness it needs to be briefly discussed that apart from the explicit navigation instruction, there can be need to redirect the user to a different route or handle unknown routes gracefully. Other sections of the router-lite documentation discusses these topics in detail. Hence these topics aren't repeated here. Please refer to the linked documentations for more details.
Fallback using the route configuration
Fallback using the viewport attribute