Skip to content
This repository has been archived by the owner on May 27, 2021. It is now read-only.

Routing

Grant Hutchinson edited this page Feb 7, 2019 · 3 revisions
⚠️ We could use your help!

If you're interested in helping us with writing documentation for this, please feel free to comment in this issue and say hi! 👋

Routing with web components can be achieved using a redux based solution with the lit-redux-router package.

Create a new app

npx create-evergreen-app my-app
cd my-app
npm start

Install Dependencies

npm install lit-element lit-html lit-redux-router redux pwa-helpers

Redux Store

Create a new redux store ./app/store.js

import { createStore, compose as origCompose, combineReducers } from 'redux';
import { lazyReducerEnhancer } from 'pwa-helpers/lazy-reducer-enhancer.js';

// eslint-disable-next-line no-underscore-dangle
const compose = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || origCompose;

// eslint-disable-next-line
const store = createStore(
  (state, action) => state, // eslint-disable-line
  compose(lazyReducerEnhancer(combineReducers))
);

export default store;

Create Pages

Create 3 new page components in ./pages/home/ e.g. docs.js, home.js, about.js

Place the following content in each, modify with the page name:

home.js

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

class HomePageComponent extends LitElement {
  render() {
    return html`
      <div class="container">
        <h1>Home</h1>
      </div>
    `;
  }
}

customElements.define('home-page', HomePageComponent);

about.js

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

class AboutPageComponent extends LitElement {
  render() {
    return html`
      <div class="container">
        <h1>About</h1>
      </div>
    `;
  }
}

customElements.define('about-page', AboutPageComponent);

docs.js

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

class DocsPageComponent extends LitElement {
  render() {
    return html`
      <div class="container">
        <h1>Documentation</h1>
      </div>
    `;
  }
}

customElements.define('docs-page', DocsPageComponent);

Setup Router

In your ./app/app.js file:

First import the dependencies

import { html, LitElement } from '@polymer/lit-element';
import { connectRouter } from 'lit-redux-router';
import store from './store.js';
import css from './app.css';
import '../components/header/header.js';

import '../pages/home/docs.js';
import '../pages/home/home.js';
import '../pages/home/about.js';

Next underneath the dependencies you need to connect the router to the store.

connectRouter(store);

Each <lit-route></lit-route> element requires a path attribute with a string for each page and component attribute with the string name of the component page element.

Within your component's render function you can add each route, here's a complete example:

import { html, LitElement } from '@polymer/lit-element';
import { connectRouter } from 'lit-redux-router';
import store from './store.js';
import css from './app.css';
import '../components/header/header.js';

import '../pages/home/docs.js';
import '../pages/home/home.js';
import '../pages/home/about.js';

connectRouter(store);

class AppComponent extends LitElement {

  render() {

    return html`
      <style>
        ${css}
      </style>

      <div>
        <eve-header></eve-header>
        <lit-route path="/" component="home-page"></lit-route>
        <lit-route path="/about" component="about-page"></lit-route>
        <lit-route path="/docs" component="docs-page"></lit-route>
        <lit-route><h1>404 Not found</h1></lit-route>
      </div>
    `;
  }
}

customElements.define('eve-app', AppComponent);

Note: When no path attribute is specified, the router will render the child elements whenever there is a 404

Path variables

Using the above example, we can modify our path attribute on any route to include path variables

for example in ./app/app.js modify:

<lit-route path="/docs/:somepage" component="docs-page'}"></lit-route>

You can then modify the ./pages/home/docs.js component to use that variable:

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

class DocsPageComponent extends LitElement {
  static get properties() {
    return {
      somepage: String
    };
  }

  render() {
    return html`
      <div class="container">
        <h1>${this.somepage}</h1>
      </div>
    `;
  }
}

customElements.define('docs-page', DocsPageComponent);

Now visit your http://localhost:1981/docs/my-test-page to see the path variable display

Navigation

To navigate route without reloading the page, modify the ./pages/home/home.js component to use store.dispatch(navigate(path)):

import { html, LitElement } from 'lit-element';
import { navigate } from 'lit-redux-router';
import store from '../../app/store.js';

class HomePageComponent extends LitElement {
  pushPath(path) {
    store.dispatch(navigate(path));
  }

  render() {
    return html`
      <div>
        <p>To get started, <button @click="${() => this.pushPath('/about')}">View About</button>
      </div>
    `;
  }
}

customElements.define('home-page', HomePageComponent);