LWR Client-Side Routing Reference
LWR provides APIs, interfaces, wires, and Lightning web components to support client-side routing.
The following data types are used in client-side routing:
- LwrRouterConfig and LwrConfigRouteDefinition
- PageReference
- RouteDefinition
- RouteInstance
- RouterConfig
- RouteDestination
- ViewSet and ViewInfo
LwrRouterConfig and LwrConfigRouteDefinition
Because static configuration can be easier to author and to maintain, you can use the Router Module Provider to generate a router based on a static JSON file. LwrRouterConfig
and LwrConfigRouteDefinition
together specify the configuration of the router module to generate. Alternately, you can use the createRouter()
API.
The LwrRouterConfig
object contains the same properties that are passed to createRouter()
:
- basePath: Optional. String. A path prefix applied to all URIs for the router. If no base path is provided, default = “”
- caseSensitive: Optional. Boolean. If
true
, URIs are processed case sensitively. Default =false
. - routes: An array of
LwrConfigRouteDefinition
objects.
Similarly, the LwrConfigRouteDefinition
object mostly contains the same properties as a RouteDefinition
object:
- id: String. Each
LwrConfigRouteDefinition
must have a unique identifier. - uri: String. A pattern for URI locations that match this
LwrConfigRouteDefinition
. The following characters are allowed:/
: path separator:parameter
: captures a variable from a path or query parameter; must be alpha-numeric (a-zA-Z0-9)?
: denotes the beginning of the query string&
: query parameter separator- *Note: The
#
and*
characters aren't allowed.*
- page: The form of page references that match this
LwrConfigRouteDefinition
.page
values can be::parameter
bindings: these map a path or query parameter from the URI to anattributes
orstate
property- literal bindings: these hard-code the
type
, anattribute
, orstate
property to a literal value; they must not contain the following reserved characters:?
,*
,#
,&
,+
,;
,(
,)
- patterns: Optional. A regular expression that a parameter must match to be valid. It’s not required, but it is recommended that the regular expression pattern is explicitly wrapped in the start-of-line character (
^
) and end-of-line-character ($
). If you don't use the start-of-line or end-of-line character, the pattern could allow unexpected values. Example:{"patterns": {"parameter": "^id[0-9a-zA-Z]{5}$"}}
- exact: Optional. Boolean, default =
true
. If there is a nested router, this value must befalse
. - metadata: Optional. Developer-defined metadata. You can use the
metadata
property to attach arbitrary additional information to aLwrConfigRouteDefinition
. By default,metadata
can contain string keys and any type values; you can extendLwrConfigRouteDefinition
for required or more strongly typed metadata. - One of the following. An
LwrConfigRouteDefinition
must contain a handler or a component, but not both:- handler: A string reference to the RouteHandler class specifier.
- component: A string reference to the view component specifier. This is a shortcut so the view component can be specified directly, without authoring a route handler.
“Generate a Router with Router Module Provider” provides an example of using LwrRouterConfig
and LwrConfigRouteDefinition
.
PageReference
An LWR router receives navigation events as page references. Page references are a JSON-format specification of a location. You pass a PageReference
object to the router via the navigate()
API.
A PageReference
object containing JSON-format locations:
- type: String.
- attributes: An array of user-defined key-value pairs or
null
if there are no attribute values. - state: An array of user-defined key-value pairs or
null
if there are no state values.
Allowed values for attributes
and state
are determined by the values you set in RouteDefinition.page
.
Example PageReference
:
RouteDefinition
The most important part of the RouterConfig
is the array of route definitions. The router uses route definitions to verify and process incoming location changes. A location is only valid if it can be matched to a RouteDefinition
. If given an invalid location, the application fails to navigate.
Each RouteDefinition
has this form:
A RouteDefinition
contains the following properties:
- id: Each
RouteDefinition
must have a unique identifier. - uri: A string pattern for URI locations that match this
RouteDefinition
. The following characters are allowed:/
: path separator:parameter
: captures a variable from a path or query parameter; must be alpha-numeric (a-zA-Z0-9)?
: denotes the beginning of the query string&
: query parameter separator- *Note: The
#
and*
characters are not allowed.*
- page: The form of page references that match this
RouteDefinition
.RouteDefinition.page
values can be::parameter
bindings: these map a path or query parameter from the URI to anattributes
orstate
property- literal bindings: these hard-code the
type
, anattribute
, orstate
property to a literal value; they must not contain the following reserved characters:?
,*
,#
,&
,+
,;
,(
,)
- handler: A Promise to a module that is called when a
RouteDefinition
is matched by a location; details in Route Definition Handlers. - patterns: Optional. A regular expression that a parameter must match to be valid. It’s not required, but it is recommended that the regular expression pattern is explicitly wrapped in the start-of-line character (
^
) and end-of-line-character ($
). If you don't use the start-of-line or end-of-line character, the pattern could allow unexpected values. Example:{"patterns": {"parameter": "^id[0-9a-zA-Z]{5}$"}}
- exact: Optional. Default =
true
). If there is a nested router, this value must befalse
. - metadata: Optional. Developer-defined metadata. You can use the
metadata
property to attach arbitrary additional information to aRouteDefinition
. By default,metadata
can contain string keys and any type values; you can extendRouteDefinition
for required or more strongly typed metadata.
RouteInstance
Location information passed to RouteHandler.update()
. The route handler receives a RouteInstance
when a new client-side navigation event occurs. The route handler uses the RouteInstance
to determine which view to show.
- id: String. The unique identifier for the `RouteDefinition.
- pageReference: The
PageReference
object for the navigation event.
RouterConfig
You use a RouterConfig
object with createRouter()
to provide information about the routes for which you want a router. A RouterConfig
object has the following form:
- routes: Optional. An array of route definitions. If no
RouteDefinition
array is supplied, the default is an empty array. Note that if you provide no value forRouterConfig.routes
, the router can’t match any locations. - basePath: Optional. String. A path prefix applied to all URIs for the router. If no base path is provided, default = “”
- caseSensitive: Optional. Boolean. If
true
, URIs are processed case sensitively. Default =false
.
RouteDestination
A route destination is provided by RouteHandler.new()
via a callback.
- viewset: A
ViewSet
object specifying the view to display.
ViewSet and ViewInfo
The view to display. You supply a ViewSet
object to a RouteDestination
.
- viewName: String. Information about the view to display. If unspecified:
default
. TheviewName
key maps to theviewName
property for the outlet. Read on for more aboutviewName
.
Because view sets can vary in complexity, the viewName
property is flexible and allows you to provide either:
- a Promise to a route handler module:
{ default: import('my/routeHandler') }
or
- a
ViewInfo
object containing both:- A Promise to a route handler module.
- A string specifier for the module. For example: "my/recipePage". Because the specifier for the module cannot be gleaned from a Promise alone, the specifier property informs the route handler of the string specifier for the module. Simple or straightforward use cases typically don’t require a specifier.
ViewInfo
example:{ default: { module: import('my/routeHandler'), specifier: 'my/routeHandler' } }
Finally, in a more advanced case, where a single page reference maps to more than one view, you can have more than one outlet, each outputting a different view component: { default: import('my/routeHandler'), sidebar: import('my/sideHandler'), footer: import('my/footerHandler') }
In LWR, modules are always provided via a Promise object. Promises allow the module code to be lazily loaded, improving application performance.
The following methods are used in client-side routing:
createRouter
Creates and initializes a router.
Syntax
Parameters
- config: Optional. Pass the
RouterConfig
object for which you want to create a router. If you don’t pass aRouterConfig
tocreateRouter()
, LWR creates a router with default values.
It is not typical to pass no RouterConfig
to createRouter()
. All RouterConfig
properties are optional, but if you don't pass any value for RouterConfig.routes
, the router can't match any locations.
Returns
A router object that you can pass to a router container component.
Usage
A router is a piece of code that manages client-side navigation changes. All navigation events flow through a router for processing. Use the createRouter()
API to initialize an LWR router.
In order to use a router in an application, it must be attached to the DOM. This is done with a router container, provided by the lwr-router-container
component. After you create and initialize the router, you receive a router object that can be passed to a router container.
“Create a Router” in Simple Client-Side Routing provides an example of using createRouter()
.
generateUrl
Generates a URL for a specified page reference.
Syntax
Parameters
-
context: The ID of the parent router container nearest to the component that is generating a URL. A
ContextId
is an opaque value that you obtain from theNavigationContext
wire. -
pageReference: The
PageReference
value for which to generate a URL.
Returns
A string with the generated URL for the given route or null
if pageReference
is invalid. If context
is invalid, generateUrl()
fails.
Usage
The “Navigate” section in Simple Client-Side Routing contains an example of using generateUrl()
.
navigate
Navigates to a page reference programmatically.
Syntax
Parameters
- context: The ID of the parent router container nearest to the component that is generating a URL. A
ContextId
is an opaque value that you obtain from theNavigationContext
wire. - pageReference: The
PageReference
value for the page to which to navigate. - replace: Optional. Boolean. If
true
,navigate()
modifies the current history entry, replacing it with the location passed in the method parameters.
Returns
None.
Usage
The “Navigate” section in Simple Client-Side Routing contains an example of using navigate()
.
When you create a route definition, it includes a promise in its handler
property to a route handler module that’s called when a location matches that RouteDefinition
.
Route handler modules determine the associated "view" — the component to display — when the application navigates to a location. Route handler modules allow you to define enhanced routing rules such as branching and pivoting logic based on data and metadata values.
You implement the RouteHandler
class interface to control the component displayed when your application navigates to a location. When a router matches an incoming location to a RouteDefinition
, it accesses RouteDefinition.handler
to determine the component to display.
The following methods are for RouteHandler
:
- new() Create a new route handler.
- dispose() Clean up a route handler.
- update() Provide a set of views for the current location.
new
Create a route handler.
Signature
Parameter
- callback: A reference to a route handler callback. Each
RouteHandlerCallback
takes aRouteDestination
object:type
RouteHandlerCallback
=
(routeDestination
:RouteDestination)
=>
void;
. Make sure to save the reference to this callback.RouteHandler.update
invokes the callback to return theViewSet
for a givenRouteDestination
/PageReference
.
Return Value
None.
Usage
Your router constructs a new route handler to determine the view for a location while processing a navigation event. The route handler uses the current location to determine the corresponding view or views. The route handler is active upon construction and can immediately emit results to the callback via update()
.
When using new()
, make sure to save a reference to the route handler callback you receive. RouteHandler Example Implementation provides an example of using new()
along with update()
.
dispose
Clean up a route handler.
Signature
Parameters
- None
Return Value
None.
Usage
RouteHandler.dispose
is called when a route handler is no longer needed by the app and no longer emits view changes. A disposed route handler cannot be used again.
update
Provide a set of views for the current location.
Signature
Parameters
- routeInfo: A
RouteInstance
providing location information. The route handler receives aRouteInstance
when a new client-side navigation event occurs and uses it to determine which view to show.
Return Value
None.
Usage
LWR calls RouteHandler.update
whenever there's a navigation event. The route handler is responsible for calculating the updated view or views. It invokes the route handler callback obtained via RouteHandler.new
to return the ViewSet
for a given RouteDestination
/ PageReference
.
RouteHandler Example Implementation
This example implements the RouteHandler interface. For additional examples: Simple Client-Side Routing.
You can use NavigationMixin
instead of the navigate()
and generateUrl()
APIs. Both options offer the same functionality, but only NavigationMixin
is compatible with Lightning Experience. So if you're writing a component for use in both LWR and Lightning Experience, choose NavigationMixin
.
The lwr/navigation
module provides wire adapters from which Lightning web components can receive information about navigation events.
The following wires are available for client-side routing:
CurrentPageReference
Get the current page reference from the router container.
This wire is also available in Lightning Experience.
Syntax
Parameters
- none
Returns
A PageReference
object containing reference to the current page.
Usage
CurrentView
Get a reference to the current view Lightning web component. An outlet uses the CurrentView
wire to get the current view component, then displays it in the DOM.
Syntax
Parameters
- viewName: Optional. Falls back to "default" if unspecified.
Returns
A reference to the current view Lightning web component.
Usage
In this snippet, the lwc:dynamic
directive uses the view component constructor returned by CurrentView
to display the current view component.
lwc:dynamic
is only available on LWC Open Source, not on the Salesforce Platform.
NavigationContext
Get a reference to a Lightning web component's navigation context (its closest ancestor router container), for use with the generateUrl()
and navigate()
APIs.
Syntax
Parameters
- none
Returns
A ContextId
. An opaque ID for the parent router container nearest to the component.
Usage
This example uses the NavigationContext
wire to obtain a ContextId
value. It assigns the ID to the navContext
property, where it can be used by the navigate()
API.
The following Lightning web components are available for LWR client-side routing:
lwr-router-container
In order to use a router in an application, it must be attached to the DOM. This is done with a router container, provided by the lwr-router-container
Lightning web component.
Router Container Properties
A router container component has the following properties:
-
router: Optional. A router object obtained from the
createRouter()
API. -
history-disabled: Optional. Boolean. Set
history-disabled
totrue
if your router container should not alter the browser's History API during navigation events/location changes.
Router Container Events
The router container component fires these events:
-
onhandlenavigation: Dispatched when
navigate(pageRef)
is called.event.preventDefault()
cancels the navigation event;event.detail
is thePageReference
. -
onprenavigate: Dispatched when a navigation event is received and a
RouteDefinition
match is found.event.preventDefault()
cancels the navigation event;event.detail
is aRouteChange
object.
- onpostnavigate: Dispatched when a navigation event has completed;
event.detail
is aDomRoutingMatch
object for the current location.
- onerrornavigate: Dispatched when there's an error processing a navigation event (for example, no
RouteDefinition
match,prenavigate
cancellation).event.detail
is aMessageObject
.
Router Container Usage
A router container provides “navigation context”. This means that the router container is responsible for processing all navigation wires and events from its descendants in the DOM (my-nav
and lwr-outlet
in the example code following).
“Create a Router” in Simple Client-Side Routing provides another example of attaching a router to a router container.
A router container can optionally have a single nested child router. Each parent router is responsible for processing the navigation events from its descendants.
Every RouteDefinition
resolving to a view component that includes a child router must set exact
to false
:
Nested Client-Side Routing provides an example of a router container with a nested child router.
lwr-outlet
A view is the component to display when the application navigates to a location. It’s an outlet's job to dynamically render those view components. The lwr-outlet
Lightning web component uses the CurrentView
wire [LINK] to get the current view component, then displays it in the DOM.
Outlet Properties
An outlet component has the following properties:
-
view-name: Optional. The key of the
ViewSet
entry to display; default value is "default". -
refocus-off: Optional. Boolean. Refocusing is on by default for accessibility. If
refocus-off
is present, the outlet does not put the browser focus on the view component when it loads.
Outlet Events
An outlet component fires these events:
- onviewchange: A handler for the
viewchange
event that is dispatched whenever the view component changes;event.detail
is the view component class.
- onviewerror: A handler for the
viewerror
event that is dispatched whenever the view component cannot be rendered;event.detail
is the error and stack.
Outlet Slot
An outlet component has the following slot:
- "error": The contents of the error slot to display if the view component fails to mount.
Outlet Usage
An outlet dynamically renders view components. The lwr-outlet
Lightning web component uses the CurrentView
wire to get the current view component, then displays it in the DOM.
This process is naturally lazy. The view isn’t imported until the outlet consumes it, so that any unused views aren’t fetched. When the router's view state changes, the outlet is flagged to display the view. At that point, if the view module hasn't already been fetched there may be an async process to retrieve it.
It's possible for a route definition handler to return multiple views, as in this example:
You can use multiple outlets to display all the current view components by setting different view-name
values: