Search code examples
javascriptweb-componentshadow-domcustom-element

error getting content from template customelement


I have a basic CustomElement but I'm having the following problem:

<template id="custom-element">
  <h1>Example 1</h1>
</template>

<script>

  class CustomElement extends HTMLElement {

    constructor() {
      super(); // always call super() first in the ctor.
      let shadowRoot = this.attachShadow({mode: 'open'});
      const template = document.querySelector('#custom-element');
      const instance = template.content.cloneNode(true);
      shadowRoot.appendChild(instance);
    }
    connectedCallback() {
      console.log("Connected");
    }

    disconnectedCallback() {

    }

    attributeChangedCallback(attrName, oldVal, newVal) {

    }
  }

  window.customElements.define('custom-element', CustomElement);

</script>

I'm getting this error in console:

Uncaught TypeError: Cannot read property 'content' of null

And it is because the const templateis always null. This was working before but I don't know if anything has changed that now it doesn't works. I'm using Chrome Version 62.0.3202.94 (Official Build) (64-bit) Any help on this please?


Solution

  • Try this:

    <template id="custom-element">
      <style>
      h1 {
        color: red;
        font: bold 24px Tahoma;
      }
      </style>
      <h1>Example 1</h1>
    </template>
    <script>
      const template = (document.currentScript||document._currentScript).ownerDocument.querySelector('#custom-element').content;
    
      class CustomElement extends HTMLElement {
        constructor() {
          super(); // always call super() first in the ctor.
          let shadowRoot = this.attachShadow({mode: 'open'});
          let instance = template.cloneNode(true);
          shadowRoot.appendChild(instance);
        }
        connectedCallback() {
          console.log("Connected");
        }
    
        disconnectedCallback() {
        }
    
        attributeChangedCallback(attrName, oldVal, newVal) {
        }
      }
    
      window.customElements.define('custom-element', CustomElement);
    </script>
    

    You need to get at document.currentScript||document._currentScript before the constructor. It must be accessed in the global space of the imported HTML file.

    I always use both together to work with all of the web-component polyfills. If you don't need the polyfill, by limiting the browsers you support, then you can just use document.currentScript.