-
Notifications
You must be signed in to change notification settings - Fork 51
Transition Rules
This guide describes how to configure route transition rules using Vaadin Router. The code examples here assume you already have an HTML page with the Router added to it. See also Simple App tutorial for the setup instructions.
The common pattern for modern web apps is to have a couple of routes for CRUD operations on the entities (articles, users etc), where each route usually consists of the following fragments:
-
/user
- the URL fragment describing the entity type -
/:id
- the route parameter pointing to the unique entity ID -
/add
- the URL fragment corresponding to the action
In some cases, the flat structure is still enough to describe the corresponding routes. However, sometimes we want to organize the router config so that it represents the structure.
Here is how you can use Child Routes feature for cleaner router config:
router.setRoutes([
{
path: '/user',
children: [
{path: '/', component: 'x-user-list'},
{
path: ':id',
children: [
{path: '/', component: 'x-user-view'},
{path: '/add', component: 'x-user-add'},
{path: '/edit', component: 'x-user-edit'},
{path: '/delete', component: 'x-user-delete'}
]
}
]
},
{path: '/:user', component: 'x-user-profile'}
]);
You could achieve same results using the flat route config structure, and copying /user
string more and more.
This structure does not affect the way how Vaadin Router loads and renders the components, but is intended to
make router config easier to understand, maintain and refactor.
Most of the web apps tend to perform certain logic when switching routes. As an example, you might want to load the data to display on the page using AJAX request, or to ensure changes are saved by the user before he leaves the page.
The common pattern for this kind of operations is to expose so-called Lifecycle Callbacks, or the functions invoked under certain conditions. Vaadin Router is meant to be used with the Web Components, which are typically defined using ES2015 classes, and the callbacks in that case are methods added to the custom element class definition.
Here is how you can add the callback to be invoked by the Vaadin Router before and after entering the page:
class UserEdit extends HTMLElement {
onBeforeEnter(location) {
return new Promise((resolve, reject) => {
const params = location.params;
fetch(`/api/users/${params.id}`).then((response) => {
// ... do something with the response
console.info('Starting render: ' + performance.now());
resolve();
});
});
}
onAfterEnter(location) {
console.info('Render completed: ' + performance.now());
}
// ... other properties, methods etc.
}
customElements.define('x-user-edit', UserEdit);
As you can see, the callback may return a Promise
, which will make route resolution asynchronous.
When switching from one route to another, the corresponding callbacks get invoked in the correct order,
giving you a full flexibility in reacting to the route changes dynamically.
At this point, you might want to ask: why do we ever need these callbacks? Aren't the native Custom Elements
callbacks, especially connectedCallback
and disconnectedCallback
, able to achieve the similar results in
most of the use cases? Shouldn't we just #UseThePlatform?
That is a valid question, and you can still use native callbacks. But relying on the adding (or removal) of the particular DOM elements might not be always the best option. Vaadin Router lifecycle callbacks give you much more, as illustrated by the sections below.
The ability to cancel navigation, also known as a "navigation guard" feature, is another widely used pattern.
Vaadin Router supports it on the component level via onBeforeLeave
and onBeforeEnter
lifecycle callbacks:
class UserEdit extends HTMLElement {
onBeforeLeave(location, commands) {
if (!this.isSaved) {
return commands.prevent();
}
}
// ... other properties, methods etc.
}
customElements.define('x-user-edit', UserEdit);
Note that all lifecycle callbacks have this
reference pointing to the component instance, so onBeforeLeave
has
access to the properties and the DOM of the rendered Web Component.
Fore more information, see Lifecycle Callbacks section in the Vaadin Router live demos.
The ability to redirect user dynamically, based on the conditions evaluated at the run time, is supported by
the Vaadin Router via onBeforeEnter
callback using special return result available from the context
object,
which is always passed to the callback when it gets called:
class UserEdit extends HTMLElement {
onBeforeEnter(location, commands) {
if (!this.isAuthorized) {
return commands.redirect('/login');
}
}
// ... other properties, methods etc.
}
customElements.define('x-user-edit', UserEdit);
As long as you organize the app logic using Web Components, these features available through lifecycle callbacks should satisfy most of the use cases. For advanced users, though, we have an alternative option to achieve the same result, while keeping the logic inside of the router config.
For detailed example, see Redirects section in the Vaadin Router live demos.