Vaadin Router

repository·main·Indexed 19 days ago

https://github.com/vaadin/router

A small, framework-agnostic client-side routing library for Web Components that maps URLs to views using express.js-style path syntax. It supports async resolution, navigation guards, and programmatic URL generation. Note: This library is no longer actively maintained; Vaadin recommends React Router, @lit-labs/router, or the native URLPattern API as alternatives.

Tokens
8.9K
Snippets
25
Records
36
Agent score
66%

What's inside @vaadin/router

  1. Vaadin Router is deprecated

    main

    Important Notice

    Vaadin Router is no longer actively maintained.

    Vaadin recommends the following alternatives:

    • React Router: The primary client-side routing tool used by Vaadin.
    • @lit-labs/router: A more lightweight and modern alternative.
    • URLPattern API: For building customized client-side routing using native browser APIs.
  2. Define Route Actions for custom logic

    main

    A route can define an action function that executes when the route is resolved. Actions run recursively from the root route down to the child route.

    An action can:

    1. Return an HTMLElement to render content.
    2. Return a PreventResult (via commands.prevent()) to stop navigation.
    3. Return a RedirectResult (via commands.redirect(path)) to redirect.
    4. Return a RouteContext to pass data down the chain.

    Actions are useful for authentication checks, data pre-fetching, or performing logic before a component is even instantiated.

  3. Access URL parameters with IndexedParams

    main

    When a route matches, parameters extracted from the URL placeholders are provided in the RouteContext.

    • IndexedParams: A read-only record where keys are the names of the placeholders in the path (or their index if unnamed) and values are ParamValue (a string, number, null, or an array of these).
    • ParamValue: Can be a single PrimitiveParamValue (string | number | null) or a readonly PrimitiveParamValue[] for repeated parameters.

    Example of how parameters are structured: If your path is /user/:id/:action and the URL is /user/123/edit, the params object will contain { id: '123', action: 'edit' }.

    export type PrimitiveParamValue = string | number | null;
    export type ParamValue = PrimitiveParamValue | readonly PrimitiveParamValue[];
    export type IndexedParams = Readonly<Record<string, ParamValue>>;
  4. Understand ActionResult and resolution results

    main

    An ActionResult<T> represents the outcome of a route's action. It defines what the router should do after the action executes.

    An ActionResult can be:

    • T: A user-defined value (the intended result of the route).
    • RouteContext<T, R, C>: A new context, used to continue the resolution process (often used in middleware).
    • NotFoundResult: Indicates the route could not be resolved.
    • null, undefined, or void.
    export type ActionResult<T> = T | NotFoundResult | null | undefined | void;
  5. Understand the RouterLocation object

    main

    The RouterLocation object describes the state of the router at a specific point in time. It is provided to view Web Components via lifecycle callbacks, as a property on the component itself, and via router.location.

    Key properties:

    • pathname: The current path (e.g., /users/42). Always starts with /.
    • params: An IndexedParams object containing named and unnamed URL parameters.
    • search: The query string portion of the URL.
    • searchParams: A URLSearchParams object for the query string.
    • hash: The fragment identifier (including #).
    • baseUrl: The base URL used by the router.
    • redirectFrom: The original pathname if the current location is the result of a redirect.
    • route: The Route object associated with this location (undefined in router.location or global events).
    • routes: A list of matching Route objects (the hierarchy from parent layouts to the view).
    • getUrl(params?: Params): A method to generate a URL for the current route, optionally overriding parameters.
  6. How route matching works in Vaadin Router

    main

    Vaadin Router traverses a routes tree from the root down to the leaves to match a given pathname. The matching process consumes parts of the pathname as it moves through parent routes to find matching child routes.

    Path Syntax Rules

    • Leading Slashes (/):
      • For the root of the routes tree, a leading / matters.
      • For all other child routes, a leading / has no significance.
    • Trailing Slashes (/):
      • Leaf Routes: A trailing / in a leaf route path matches only if the pathname also has a trailing /.
      • Child Routes: A trailing / in a route path does not affect how its children are matched.
      • Pathnames: Trailing slashes in the pathname generally do not affect matching, except when matching leaf nodes.
    • Special Routes ("" and /):
      • As a single route: "" matches only "" pathnames; / matches only / pathnames.
      • As a parent: "" matches any pathname without consuming any part of it; / matches any absolute pathname by consuming its leading /.
      • As a leaf: Both "" and / match only if the entire pathname has been consumed by the parent chain.
      • Squashing: Directly nested "" or / routes are 'squashed', meaning nesting two / routes does not require a double // in the pathname.

    Matching Behavior

    The matching process returns a lazily evaluated iterator. This allows for traversing the matches found in the tree. If a route has children: true (or has a children array), prefix matching is enabled.

    Side Effect Note: A routes tree defined as { path: '' } matches only the '' pathname. However, a tree defined as { path: '', children: [ { path: '' } ] } will match any pathname because the root matches the empty string without consuming anything.

  7. Handle lifecycle hooks: `onBeforeEnter` and `onAfterLeave`

    main

    Web Components rendered by the router can implement lifecycle methods to react to navigation changes:

    • onBeforeEnter(location, commands): Called before the component is attached to the DOM. Use this to prevent navigation or perform redirects.
    • onAfterLeave(location, commands): Called after the component is removed from the DOM.

    These methods receive a location object containing the current route information and a commands object for interaction.

  8. Use Route Actions for logic and control

    main

    An action function is the most powerful way to control route resolution. It is called before the route is resolved and can return several types of results to influence the outcome:

    • Return an HTMLElement: The route is resolved to this specific element.
    • Return commands.component(name): The route is resolved to the specified Web Component.
    • Return commands.redirect(path): The current navigation is aborted and a redirect to the new path is initiated.
    • Return context.next(): Asynchronously requests the next route in the resolution chain.
    • Return prevent(): Cancels the navigation entirely.

    Important: If you use an arrow function for action, you will not have access to the route object via this. Use a standard function if you need to access the route object.

    // Example of an action using commands
    {
      path: '/admin',
      action(function(context, commands) {
        const isAdmin = checkAuth(); // your logic
        if (!isAdmin) {
          return commands.redirect('/login');
        }
        // If we return nothing, it proceeds to use the 'component' property
      }),
      component: 'admin-view'
    }
  9. Migrate from V1 to V2: Deprecated Types and Interfaces

    main

    If you are migrating from Vaadin Router v1 to v2, several types and interfaces have been renamed or replaced. Use the following mapping to update your codebase:

    V1 Type/InterfaceV2 Replacement
    ComponentResultHTMLElement
    ContextRouteContext
    ActionFnNonNullable<Route['action']>
    ChildrenFnChildrenCallback
    BeforeEnterObserverWebComponentInterface
    BeforeLeaveObserverWebComponentInterface
    AfterEnterObserverWebComponentInterface
    AfterLeaveObserverWebComponentInterface

    Note that the observer interfaces (BeforeEnterObserver, etc.) are now consolidated into the WebComponentInterface.

  10. Initialize the Vaadin Router

    main

    To use Vaadin Router, create a new instance of the Router class. You must provide an outlet (the DOM node where route content will be rendered) and optionally a RouterOptions object.

    The router automatically subscribes to navigation events on the window upon instantiation. If you provide a baseUrl in the options, it will be used for all relative routing.

    Note: This library is deprecated. Vaadin recommends using React Router or the URLPattern standard Web API.

    // Basic initialization
    const router = new Router(document.getElementById('outlet'));
    
    // Initialization with options
    const router = new Router(document.getElementById('outlet'), {
      baseUrl: '/my-app/'
    });
  11. Implement Web Component lifecycle callbacks for routing

    main

    Vaadin Router automatically calls specific methods on your view Web Components during the navigation lifecycle. You do not need to extend a specific class; simply defining these methods is sufficient. Methods can be synchronous or return a Promise.

    Use these methods to intercept navigation, prevent it, or redirect the user:

    • onBeforeEnter(location, commands, router): Called before the outlet is updated.
      • Return commands.prevent() (or a Promise resolving to it) to abort navigation.
      • Return commands.redirect(path) (or a Promise resolving to it) to start a new navigation cycle to the new path.
    • onBeforeLeave(location, commands, router): Called when navigating away from the component.
      • Return commands.prevent() to abort the navigation.

    Post-Navigation Hooks

    Use these methods for setup or cleanup after the DOM has been updated:

    • onAfterEnter(location, commands, router): Called asynchronously after connectedCallback() once the outlet has been updated with the new element.
    • onAfterLeave(location, commands, router): Called when the component is being removed from the DOM. Note that this method cannot prevent navigation; the component is already being resolved for removal.
    class MyView extends HTMLElement {
      async onBeforeEnter(location, commands, router) {
        const isAuthorized = await checkAuth();
        if (!isAuthorized) {
          return commands.redirect('/login');
        }
      }
    
      onAfterEnter(location, commands, router) {
        console.log('View entered:', location.pathname);
      }
    }