Render web components according to router state. Provides advanced funcionality like lazy loading, nested components and routing control though lifecycle hooks.
Can be configured as a string with the web component tag name, as an class constructor (HTMLElement descendant) or as a function which must resolves to an tag name or constructor.
The function is called with route configuration as argument and is only executed when the route is entered. If is async, it waits to be resolved.
import './components/home-view.js'
import LoginView from './components/login-view.js'
function AboutView () {
return import('./components/about-view.js')
}
const routes = [
{
name: 'home',
component: 'home-view'
},
{
name: 'login',
component: LoginView
},
{
name: 'about',
component: AboutView
}
]
When using dynamic import with a tool like webpack the corresponding code is split from main bundle and lazy loaded
By default, the routes elements are created each navigation even when the same route is matched.
Setting reuse
to true will make the router reuse the same element instance when the same route is matched
const routes = [
{
name: 'person',
component: 'person-view',
path: 'person/:id',
reuse: true
}
]
In the above example transitioning from 'person/1' to 'person/2' will not create a new 'person-view' element.
The lifecycle hooks will be fired and $route
property will be updated
Defines the properties that are set to the route element.
Its a hash where the key is the property name and the value is either a primitive a value (string, number) or a property hook (see below)
// navigating to 'hello' will render a message-view element with message set to 'Hello'
// navigating to 'goodbye' will render a message-view element with message set to 'Goodbye'
const routes = [
{
name: 'hello',
component: 'message-view',
properties: {
message: 'Hello'
}
},
{
name: 'goodbye',
component: 'message-view',
properties: {
message: 'Goodbye'
}
}
]
Property hooks provides a way to intercept routing lifecycle and set properties dynamically
Its a object with the following methods:
init
- called first time the route is entered. Its called with a setter functionenter
- called after the route is entered. Its called with the current transition and a setter functionleave
- called after the route is leave. Its called with the current transition and a setter functionupdate
- called when the property value is updated by one of the other methods. Its called with the new value and element instance
The following builtin hook factories are provided:
fromParam
: sets the property from a route param. Accepts akey
parameter to define the param to retrieve from and a optionalformat
parameter to convert the valuefromQuery
: sets the property from a route query. Accepts akey
parameter to define the query to retrieve from and a optionalformat
parameter to convert the valuefromValue
: sets the property from a value. Accepts avalue
parameter to define the value to set
The format
parameter can be 'number' to convert to number or a function to do custom formatting
import { fromParam, fromQuery } from 'slick-router/middlewares/wc'
const routes = [
{
name: 'person',
component: 'person-view',
path: '/person/:id'
properties: {
personId: fromParam('id', 'number')
}
},
{
name: 'people',
component: 'people-view',
properties: {
sort: fromQuery('sort', value => value.toUpperCase())
}
}
]
In the above example, when path is 'person/2' the rendered element of person route will have personId set to 2. When path is 'people?sort=asc' the people route element will have sort set to 'ASC'
** Custom property hooks **
// reads a value from local storage each time the route is entered
function fromLocalStorage(key) {
return {
enter(transition, set) {
set(localStorage.getItem(key))
}
}
}
// reads a value from a DI container first time the route is entered
function fromService(service) {
return {
init(set) {
const value = someServiceContainer[service]
set(value)
}
}
}
// reads a value from a store and updates the element property when the store changes
// useful for libraries like reatom or nanostores
function fromDataStore(store) {
return {
enter(transition, set) {
this.unsubscribe = store.subscribe(value => set(value))
}
leave() {
this.unsubscribe && this.unsubscribe()
}
}
}
const routes = [
{
name: 'person',
component: 'person-view',
path: '/person'
properties: {
personId: fromLocalStorage('personId'),
dbApi: fromService('dbApi'),
appUser: fromDataStore(appUserStore)
}
}
]
Function that is called before the route is entered. A transition
instance is passed as argument allowing to manipulate it, e.g., cancel or redirect.
In nested routes, is called from parent to child
It can be an async function in which case is awaited before proceeding.
const routes = [
{
name: 'settings',
beforeEnter: (transition) => {
if !isLogged() {
transition.redirectTo('login')
}
}
}
]
If
beforeEnter
returns false, the transition is cancelled
Function that is called after the route is entered. A transition
instance is passed as argument but trying to manipulate it, e.g., cancel or redirect will not have effect
In nested routes, is called from parent to child
Even if is an async function it will not be awaited before proceeding.
Function that is called before the route is about to leave. A transition
instance is passed as argument allowing to manipulate it, e.g., cancel or redirect.
In nested routes, is called from child to parent
It can be an async function in which case is awaited before proceeding.
const routes = [
{
name: 'settings',
beforeLeave: async (transition) => {
return await asyncDialog('Are you sure you want to leave?')
}
}
]
If
beforeLeave
returns false, the transition is cancelled
Function that is called after the route is leave. A transition
instance is passed as argument but trying to manipulate it, e.g., cancel or redirect will not have effect
In nested routes, is called from child to parent
Even if is an async function it will not be awaited before proceeding.
Routing state can be acessed in component instance methods
Called with transition
instance as argument before is inserted in the dom tree. Exhibits same behavior as beforeEnter
class HomeView extends HTMLElement {
beforeRouteEnter(transition) {
console.log('Before entering in home')
}
}
Called with transition
instance as argument before is inserted in the dom tree. Exhibits same behavior as afterEnter
Called with transition
instance as argument before is removed from the dom tree. Exhibits same behavior as beforeLeave
class FormView extends HTMLElement {
async beforeRouteLeave(transition) {
if (!this.dataIsSaved()) {
return await asyncDialog('Data not saved. Are you sure to leave?')
}
}
}
Called with transition
instance as argument after is removed in the dom tree. Exhibits same behavior as afterLeave
Routing related properties set to components
Associated router instance
Object holding active route state:
{
routes, // matched routes
path,
pathname,
params,
query
}