Skip to content

Transition Rules

web-padawan edited this page Jul 6, 2018 · 3 revisions

Introduction

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.

1. Child Routes

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.

2. Lifecycle Callbacks

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.

3. Prevent Navigation

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.

4. Dynamic Redirects

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.