Search code examples
shadow-domcustom-elementhtml-templatesjavascript-inheritance

How to overwrite part of <template> element in custom element inheritance?


I have parent Custom Element, BasicSwitcher, which has its shadow dom html template:

const template_basic_switcher = document.createElement('template');
template_basic_switcher.innerHTML = `
<style>
    @import url("https://use.fontawesome.com/releases/v5.6.3/css/all.css")
</style>

<div id="controls-container">
    <span>ON</span>
    <span>OFF</span>
</div>
`;

Now I have another Custom Element, ModeSwitcher, inheriting from BasicSwitcher. It has completely different switches.

Is there a way to overwrite just the controls-container part of the template, while still utilizing other part? the element doesn't seem to support any kind of inheritance.


Solution

  • 1) Create class for you Base Custom Element with a defaut render() method.

    class BasicSwitcher extends HTMLElement {
        render() {
            this.shadowRoot.innerHTML = baseTemplate      
        }
    }  
    

    2) Extend the above class for your inherited Custum Element, and redefine the render() method and use the reference to the new template.

    class ModeSwicher extends BasicSwitch () {
        render() {
            this.shadowRoot.innerHTML = otherTemplate      
        }
    }  
    

    Below is a working snippet:

    class BasicSwitcher extends HTMLElement {
        constructor() {
            super()
            this.attachShadow( { mode: 'open' } )
            this.render()
        }
        render() {
            this.shadowRoot.innerHTML = BS.innerHTML
        }
    }
    customElements.define( 'basic-switch', BasicSwitcher ) 
    
    class ModeSwitcher extends BasicSwitcher {
        render() {
            this.shadowRoot.innerHTML = MS.innerHTML
        }
    }
    customElements.define( 'mode-switch', ModeSwitcher )
    <template id=BS>
      <style> :host { display: inline-block ; border: 1px solid gray } </style>
      <span>Basic Switch</span>
    </template>
    
    <template id=MS>
      <style> :host { display: inline-block ; border: 1px dotted blue ; color: red } </style>
      <span>Mode Switch</span>
    </template>
    
    <basic-switch></basic-switch>
    
    <mode-switch></mode-switch>