Routing and Web Components
Exploring Vaadin Router; a Web Component routing library.

The Problem
By default, single-page-applications (SPAs) have a single URL. Navigating between screens does not change the URL; nor is there a mechanism to deep link to a particular screen using an URL.
Each of the popular front-end frameworks have their solution:
- React has React Router
- Angular has Angular Router
- Vue.js has vue-router
But what about for Web Components?
The Solution
Turns out that there is a Web Component framework-agnostic solution; Vaadin Router that is fairly easy to use and is surprisingly robust.
Unfortunately, the Vaadin Router’s documentation is fairly terse and as such requires some interpretation.
The Example
To illustrate the use of Vaadin Router, we will walk through using it in a vanilla (no framework) Web Component application example; it is available for download.
First, if you are unfamiliar with Web Components, this article builds upon another series of articles starting with Web Components in 2019: Part 1.
note: One deviation from that series is that this example uses ESLint instead of TSLint; described in the article From ESLint to TSLint and Back Again.
Basic and Fallback Routes
The entry point, src/index.ts, to the application imports all the components used in routing and maps URL paths to them, e.g., loading the root, i.e., /, URL loads the Home component as the child of the root element; connecting it to the DOM.
The basic routes are /, /a, and /b; loading the components Home, A, and B respectively. The last route is a regular expression matching any string and thus serves as a fallback route (served if nothing more specific matches) loading the NotFound component.
Note: This code requires a web server that supports applications that manipulate the browser history, e.g., this example uses webpack-dev-server and it’s historyApiFallback feature for development.
Routing and Web Components
By default, the browser treats following links, i.e., a tags, and back navigation as page loads; thus breaking single-page-applications. Loading Vaadin Router, however, changes the browser’s default behavior and maps these events to Vaadin Router navigation events.
One immediate problem however, is that only a tags in the Light DOM when Vaadin Router is loaded have their functionality mapped; specifically a tags in a loaded web component’s DOM retain their default behavior (loading pages).
What to do?
Luckily, Vaadin Router provides a static method, go, on the supplied Router class that triggers Vaadin Router navigation events. For example, the A component provides a link back to the root, /, route; in src/a.ts:
Nested Routes
Vaadin Router takes advantage of the Web Component slot feature to allow one to nest routes, e.g., navigating to the /nav/a route (see src/index.ts above) loads the A component loaded into the Nav component’s singular slot; src/nav.ts:
Route Parameters
So far we have been routing based on fixed routes, i.e., determined at compile-time. What about routes that are determined at run-time?
In this case, we can use a parameterized route, e.g., /fruit/:id (see src/index.ts above). In order to access the route parameters in the loaded component, we implement Vaadin Router specific lifecycle methods, e.g., onAfterEnter, on the component. In this specific example, we access the id parameter in the Fruit component; src/fruit.ts:
Wrap Up
With this, we have covered most of what would expect of single-page-application routing solution. Hope you found this useful.
Addendum
One thing that I neglected to mention is that Vaadin Router does not ship with TypeScript definitions; nor is there a published one in DefinitelyTyped. So in order to use it in this example, we can create our own minimal TypeScript definition file to use it in this example; src/types/router.d.ts: