rich-component

library providing means to work conveniently with HTML based Web Components

Usage no npm install needed!

<script type="module">
  import richComponent from 'https://cdn.skypack.dev/rich-component';
</script>

README

GitHub npm Travis Codecov Codacy

Summary

rich-component provides a set of means to easily manage WebComponents with HTML template.

Terms web component and custom element are used interchangeably here.

It helps order and cleanness freaks like myself to separate easily the HTML/CSS from the JavaScript.

rich-component ensures correctness of the provided template, fetches/caches the template when needed and injects it into the shadow/light of each newly created component instance.

Few points to stress:

  • rich-component is very small in itself and has very narrow defined functionality, it's more like a utility or a micro-framework, than a full blown beast
  • simplicity is one of the primary things the author concerned with
  • APIs designed to second the native component definition APis, so migration to & from rich-component requires minimal effort - it's not binding you to anything
  • when template needs to be fetched over the network, the custom element definition postponed to that, thus making the component available to the application only when ready to use (dynamic URL case being an exception)
  • template's content defaultly added to an open shadow DOM; one may opt adding it to a light DOM.

Customized built-in elements are not yet supported, will extend the library if/when that spec will become widely supported by browsers.

Last versions (full changelog is here)

  • 1.8.0

    • implemented issue #8
      • added dynamic html URL provisioning
    • updated dependencies versions
  • 1.7.0

    • implemented issue #8 - added test and documentation of already available functionality
    • updated dependencies versions
  • 1.6.0

    • updated dependencies versions
    • adjusted the repo and the dist to the better practice (dist is not committed but published only)

Usage

The workflow is ultimately simple:

  • import rich-component's API
  • define your component's class extending library's ComponentBase class, which extends HTMLElement
  • part of your class implementation should provide a template for your custom element (see API documentation for the details)

Basic example

Lets assume, that the template is found in my-element.html file.

We can now define the my-element component in the my-element.js (assuming it located beside my-element.html):

import { initComponent, ComponentBase } from './dist/rich-component.min.js';
...

initComponent('my-element', class extends ComponentBase {

  ...

  static get htmlUrl() {
        return import.meta.url.replace(/js$/, 'html');
    }
});

Of course, URL of HTML may be given any other way, even hardcoded, but I've found myself typically using the above pattern, making components look uniformly.

Having the code as above, rich-component will do the following steps:

  • first ensure a properly defined template source, failing fast if otherwise
  • then fetch the template and cache it
  • define the custom element in registry
  • inject the template into the shadowRoot each time my-element is constructed

Dynamic resolution example

For the best readability and predictability of the flow, it is most advised to staticly provide the template URL (or template content) upfront.

Sometimes it is required to switch the template dynamically, based on instance attributes, for example.

For those use cases template / htmlUrl may return a function.

That function will be called during element's construction and expected to return a template or template URL (correspondingly to getter).

Consider the following example of dynamic template:

initComponent('my-element', class extends ComponentBase {

  static get template() {
        return self => {
            return self.hasAttribute('readonly') ? x : y;
        };
    }
});

In the example above, getter template provides a function, which will be called each instance construction returning relevant template (in our example x/y) based on instance attribute.

Using the rich-component with 'inline' templates may still be convenient and provide some kind of a future proofness, making it an easy task to externalize HTML/CSS part when overgrown. Yet, IMHO it would also be perfectly right to not use rich-component at all in such a cases, but fall-back to the native API.

Detailed API is here.