Web Components Nested Rerender

Published on 26 July 2023

I have this idea, that if I build something "not at work", but, so to say, "for kicks", then I should not use dependencies and implement every little thing myself. Why? Simply because I believe that nothing a simple side project requires is too complicated to write yourself, and because achieving most of the same things that are possible with dependencies without them is a great way to learn the principles and ideas behind the said dependencies. 

For example, I am constantly building and rebuilding a CMS for smaller projects. The idea behind it is to give the website owners (non-programming folks) convenience of Wordpress Admin, but without the owners having to pay for hosting. I am achieving this by building a light admin interface, that allows:
  1. user authentication and editing access by using a GitHub account
  2. CRUD on a schema defined data
For the first version I used Preact and its hooks for data management, but I am not happy with that, as I’d like to implement the component framework myself or not use one at all. 

I want to learn web components and see whether they can allow the things I find ergonomic for writing UI. So, I attempt to rewrite my first version of the admin UI using web components.

Generally I want an easy way to: 
  1. create a state store 
  2. subscribe to its changes
  3. rerender the views based on these
  4. provide the views with a way to trigger changes on the state
I need to be able to express the following

const state = new Store({ 
  isAuthorised: false,
  menu: [{ path: '/', title: 'Home', path: '/products', title: 'Products' }],
  pages: [],
})

class AppView extends Component {
  onAuthorise() {
    state.isAuthorised = true;
  }
  template({isAuthorised}) {
    // using HTML template could be better,
    // because that way HTML parser is used and not a simple 
    // string concantenation
    return `<div>${isAuthorised 
      ? `auth’d` 
      : `<button></button>`
    }</div>`
  }
  events: {
    'onClick button': this.buttonOnClick
  },
}
const view = new View(state);

state.on('datachange', (event) => {
  view.rerender(event.changed);
});