JaySunSyn / web-component-router

Simple web component router

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Simple Web Component Router

alt text

This is a simple web component router that hooks into both the history API and the web components API. You can use this to setup routing for your web components application.

Features:

  • Dynamic imports (Lazy loading for javascript modules)
  • Simple setup
  • Flexibility using either the render method or a component name for rendering a route

Documentation:


Getting started

Installation

npm install simple-wc-router --save
yarn add simple-wc-router

Usage

You can import the Router and/or RouteMixin from the package and use it to extends the web component class

import { Router, RouteMixin } from 'simple-wc-router';

class SomeComponent extends Router(SomeWebComponentLibrary) {

Router

To make sure the routing works as intended, please add a base tag to your root HTML page, like so:

<base href="/">

The base href itself does not have to be /.

The Router is a class mixin which you can use to extend your webcomponent. The following example will show you how to use it.

Exampe with Lit Element

You can make use of dynamic imports if your build tooling supports it. If not make sure the components have been (imported and) defined. The imported component will be passed a routeProps object containing (in this case) a property type and day for the page-stocks component.

Wilcard/Fallback/Default routes can be added as path: "*", which can be used with either render or component (with or without import).

As of version 1.2.0 the routes need to be defined as static get routes().

As of version 2.1.0 a render method is added to the route definitions`.

app.js

import { LitElement, html } from 'lit-element';
import { Router } from 'simple-wc-router';
import './pages/page_home';
import './components';

const globalProp = "version-1.2.3";

class App extends Router(LitElement) {
    static get routes() {
        return [
            {
                path: "/",
                component: "page-home"
            },
            {
                path: "/stock/:type/:day",
                component: "page-stocks",
                import: () => import("./src/page_stock.js")
            },
            {
                path: "/news/:category",
                render: routeProps => html`
                    <page-news 
                        .category=${routeProps.category} 
                        .someOtherGlobalProp=${globalProp}>
                    </page-news>`,
                import: () => import("./src/page_news.js")
            },
            {
                path: "*",
                render: () => html`<h2>404 The requested page could not be found</h2>`
            }
        ];
    }
    render() {
        return html`
            <app-header>
                <h1 slot="left">... some title goes here ...</h1>
                <nav slot="right">... some navigation goes here ...</nav>
            </app-header>
            <main>
                ${this.routeElement}
            </main>
            <app-footer>
                ... some copyright goes here ...
            </app-footer>
        `
    }
}
customElements.define('my-app', App);

page_stocks.js

import { LitElement, html } from 'lit-element';

class Stocks extends LitElement {
    render() {
        // If provided, the properties for type and day are taking from the path.
        const { type = 'NASDAC', day = 'monday' } = this.routeProps;
        return html`This is the page for ${type} on a ${day}`
    }
}
customElements.define('page-stocks', Stocks);

RouteMixin

The RouteMixin class should be used for those components that trigger navigation. The navigate method is added to the class, which only requires you to set a route property. The navigate method can also be called with a route. The mixin also provides you a boolean that tells you if the given route is active (isRouteActive) which you can utilize for e.g. styles.

import { LitElement, html, css } from 'lit-element';
import { RouteMixin } from 'simple-wc-router'; 

class Button extends RouteMixin(LitElement) {
    static get properties() {
        return {
           route: String,
           disabled: Boolean
        }
    }
    static get styles() {
        return css`
            :host > button.active {
                color: red;
            }
        `;
    }
    handleClick() {
        if (this.disabled) this.navigate('/button-was-disabled-why-did-you-click-it');
        this.navigate();
    }
    render() {
        const activeClass = this.isRouteActive ? 'active' : '';
        const clickHandler = this.handleClick.bind(this);
        return html`
            <button class="${activeClass}" @click="${clickHandler}">
                <slot></slot>
            </button>
        `;
    }    
}
customElements.define('w-button', Button);

Now when you want to use the component, it is as simple as:

<w-button route="/foo/bar">The only bar in town... FooBar</w-button>

Changelog

Version Changes
1.0.0 Initial version of simple web component router
1.0.1 Small bugfix
1.0.2 Another small bugfix
1.1.0 Changed the routing setup
2.0.0 Changed route matching, routes must be defined as static. Also created example to play around.
2.1.0 Added a render method to the route definition.
2.2.0 Added wildcard posibility.
2.2.1 Changed the documentation.
2.3.0 Added support for optional path parts.

About

Simple web component router


Languages

Language:JavaScript 95.4%Language:HTML 4.6%