Navigating
Learn to navigate from one view to another using the Router-Lite. Also learn about routing context.
Last updated
Learn to navigate from one view to another using the Router-Lite. Also learn about routing context.
Last updated
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 resolve(IRouteContext)
. 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 resolve(IRouteContext)
. 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