DEV Community

Frank Lemanschik
Frank Lemanschik

Posted on • Edited on

The HTML Component Pattern HCP

I am at Present Promoting the HTML Component Pattern that i have invented and want to exchange it more with the world to get Response from none Senior Devs if they understand it or not.

I found on this page this article and thought I should Post my Pattern here.

I also hate react for what they did with the Specs and how they try to compensate that with even more bad code.

A Little CodePen to play with https://codepen.io/frank-dspeed/pen/xxGRYxp?editors=1011

So let me start to introduce the pattern I will let you think about it.

The Rules:
Return always String and let the Browser do the Execution we call this Declarative Templating.

Here is a basic HTML Component no custom-element is needed to Archive our Goal while we could use customElement api if we want to but we have no need most times if we only use the connectedCallback the Script tag is like a custom Controlled connectedCallback or let us Say ComponentDidMount Hook

<!-- gets processed before DOMContentLoaded -->
<p>My <span>component</span></p>
<script defer>{
    const customElement = document.currentScript.previousElementSibling;
    customElement.querySelector('span').innerText = 'Component'
    customElement.innerHTML += ' Works!';
}</script>

this example defers also code execution and Component Handling to be executed after DOMContentLoaded event the example before will be executed before DOMContentLoaded

<p>My <span>component</span></p>
<script defer>{
    const customElement = document.currentScript.previousElementSibling;
    document.addEventListener('DOMContentLoaded', () => {
      customElement.querySelector('span').innerText = 'Component'
      customElement.innerHTML += ' Works after DOMContentLoaded!';
    });  
}</script>
//import.meta.scriptElement.getRootNode()

I hope you get the idea and that I could give you some insights into how the Browser Works. As the First that a Browser does is Parsing HTML it makes sense to Work with HTML to control the Loading pipeline.

I also want to show a class based Example

This is the customElement aka Component

lets call the file my-element.js


export class myElementDefinition {
 connectedCallback() {
      this.querySelector('span').innerText = 'Component'
      this.innerHTML += ' Works after DOMContentLoaded!';
 }

}

index.html


<p>My <span>component</span></p>
<script defer>{
    const customElement = document.currentScript.previousElementSibling;
    // Download the Module and Instantiate it but don't use it
    // Thanks to defer this gets done in parallel none-blocking.
    const myElementModule = import('./my-element.js')
    document.addEventListener('DOMContentLoaded', async () => {
      // At this Stage our Module is fetched and Instatiated lets use it
      const { myElementDefinition } = await myElementModule
      const { connectedCallback } = myElementDefinition.prototype
      connectedCallback.apply(customElement)
    });  
}</script>

If you wonder why the hell I used apply and all that this is related to the customElement Spec its the same process that the Browser uses to register nativ customElement definitions.

And Please comment any suggestions or problems that you have with this Pattern thanks a lot happy coding.

Final lets show NodeJS SSR of such a Component

import fs from 'fs'
// This references the index.html from prev example assuming everything in same folder

function requestHandler(req,res) {
   res.end(`<html><body>${fs.readFileSync('./index.html')}</body></html>`)
}

This illustrates that we can render such components and the component handles it self the loading

Note for my Self

I should expand on this to a few other general topics like

  • How to Import a .html file as single file component.
    • In that i should introduce the template tag
  • I should show inharitance. of HTML Components.
  • I Should show Reactive State via Stream Observeables

Top comments (3)

Collapse
 
isaachagoel profile image
Isaac Hagoel

I used similar approaches when creating vanilla components in the past, when the App needed to support browsers that didn't have customElements.define(...) :)
This is a nice start but I think there is still a lot missing.
One thing you might want to add are ways to easily put your components in templates, find them in the DOM, call DOM operations on them (as in myComponent.addEventListener) and so on.
On top of that there are the problems that modern frameworks are trying to solve regarding auto refreshing your views as your 'state' changes in a performant manner.

Collapse
 
frankdspeed profile image
Frank Lemanschik

nice to hear that from you and yes there is more stuff to solve and there are a lot of ways to solve them. The view part ist interristing i will keep you updated because i solve that via Streams to compose Observeable State for DOM Updates.

Collapse
 
triloworld profile image
Patryk Padus

RequireJS, Backbone enable this approach and Vue use it on whole new level that concept to success. In Core Vue is a way to force standard on String. No one do it on Vanilla as this go out of control.