page.js icon indicating copy to clipboard operation
page.js copied to clipboard

PageJS and WebComponents

Open aress31 opened this issue 3 years ago • 3 comments

Hi everyone,

I am considering moving from Vaadin Router to PagesJS since PagesJS is almost half the size. I am creating a project using web components - https://github.com/open-wc/open-wc - I need to have a centralized place where I configure the router (ideally using a JSON object of all my routes) and make it accessible application wide.

What would be the best way to proceed?

Thanks in advance, Alex

aress31 avatar Aug 08 '20 12:08 aress31

I use it in a web component based app so I'll just share a snippet.

class MyApp extends HTMLElement {
  constructor() {
    super();
    this.currentPage = 'home';
  }

  connectedCallback(c) {
    this.setupRouting();
  }

  setupRouting() {
    page('*', (ctx, next) => {
      // do stuff on each page request
      next();
    });

    page('/', () => {
      this.currentPage = 'home';
      this.pageTemplate = html`
        <jb-home></jb-home>
      `;
    });
  
    page('/work', () => {
      this.currentPage = 'work';
      this.pageTemplate = html`
        <jb-work></jb-work>
      `;
    });
  
    page();

    this.addEventListener('change-route', e => {
      page(`/${e.detail}`);
    });
  }

  render() {
    this.innerHTML = `
      <jb-nav></jb-nav>
      ${this.pageTemplate}
    `;
  }
}

This app shell is the top most component in my app, you just re-render whenever currentChange property changes. Simplest way is to create getter/setter for it, reflect to an attribute, and listen for attributeChangedCallback, and call the render method when the value of the attribute is different than current. That, or add a MutationObserver or something. Libraries like LitElement, stencil, Fast element, etc. etc. all provide you with easy helpers for changing props + re-rendering what has changed.

Some component deep deep down that has a click that changes the route

<jb-button
  @click=${() =>
    host.dispatchEvent(
      new CustomEvent('change-route', { bubbles: true, composed: true, detail: 'work' }),
    )}
  >EXPLORE WORK</jb-button
>

This event gets caught in the app shell on the event listener for change-route, if you set composed:true it also goes through shadow dom boundaries. The "normal" way would just be through anchors with href attributes though, usually.

jorenbroekema avatar Aug 09 '20 07:08 jorenbroekema

Did anyone else try this with webcomponents ? ( Lit in particular )

klauss194 avatar Mar 26 '24 23:03 klauss194

Lit works with it as well, very similar to my snippet using HTMLElement, except you use LitElement

jorenbroekema avatar Mar 27 '24 00:03 jorenbroekema