Search code examples
javascriptweb-componentcustom-elementhtml-importshtml5-template

web component (vanilla, no polymer): how to load <template> content?


i'm new on web component. I checked some example, but i really can't figure out how to load (insert in the DOM) the content of a of a separate web component. Starting from this example , I put this code in a file named my-element.html:

<template id="my-element">
  <p>Yes, it works!</p>
</template>
<script>
    document.registerElement('my-element', class extends HTMLElement {
      constructor() {
      super(); 
      let shadowRoot = this.attachShadow({mode: 'open'});
      const t = document.querySelector('#my-element');
      const instance = t.content.cloneNode(true);
      shadowRoot.appendChild(instance);
    }
});
</script>

This is my index.html:

<!doctype html> 
<html>
 <head>
   <meta charset="utf-8">
   <title>my titile</title>
   <link rel="import" href="my-element.html">
</head>
<body>
  Does it work?
  <my-element></my-element>
</body>
</html>

I'm on latest Chrome 56, so i don't need polyfill. I run polyserve, and only "Does it works?" appears. I tried (like the original example) the "customElements.define" syntax instead of "document.registerElement", but won't work. Have you some ideas? And what have I to change if i don't want to use shadow dom?

thanks


Solution

  • It's because when you do:

    document.querySelector( '#my-element' );
    

    ...document refers to the main document index.html

    If you want to get the template, you should use instead document.currentScript.ownerDocument

    var importedDoc = document.currentScript.ownerDocument;
    customElements.define('my-element', class extends HTMLElement {
          constructor() {
              super(); 
              let shadowRoot = this.attachShadow({mode: 'open'});
              const t = importedDoc.querySelector('#my-element');
              const instance = t.content.cloneNode(true);
              shadowRoot.appendChild(instance);
        }
    });
    

    Note that document.currentScript is a global variable, so it refers to your imported document only when it is currently parsed. That's why it's value is saved in a variable (here: importedDoc) to be reusable later (in the constrcutor call)

    If you have multiple imported document you may want to isolate it in a closure (as explained in this post):

    ( function ( importedDoc )
    {
        //register element
    } )(document.currentScript.ownerDocument);