0

I'm trying to understand how the different parts of vanilla web components work together. I have defined a simple custom component and am trying to include a template. I'm doing this since many browser vendors are not supporting html imports and moving towards using es6 modules instead. Here's my web component:

var tmpl = `<template>
<h1>header</h1>
<p>copy</p>
</template>`;

class MyComponent extends HTMLElement {
    constructor() {
        super();
    }
    connectedCallback() {
        let z = tmpl.cloneNode(true);
        this.appendChild(z);
    }
}

customElements.define('my-comopnent', MyComponent);

The error I get is Uncaught Type Error: cloneNode is not a function I imagine that has something to do with the way I am defining my template as a string.

My question is this: how do I stamp out my template in a custom component where the template is defined as a javascript string literal? Can I do so without additional dependencies or npm libraries?

rakitin
  • 1,943
  • 6
  • 25
  • 51

1 Answers1

1

Looking at https://developer.mozilla.org/en-US/docs/Web/API/Node/cloneNode cloneNode is a method that is on the Node interface.

In your code tmpl is not a Node but a string.

You need to do something like this at the top of your code:

let tmpl = document.createElement('template');
tmpl.innerHTML = `
<h1>header</h1>
<p>copy</p>
`;
sideshowbarker
  • 81,827
  • 26
  • 193
  • 197
itodd
  • 2,278
  • 1
  • 14
  • 14
  • Thanks @sideshowbarker, edit is ok - (1) `template` was not in the innerHTML..? (2) I was going to update the string to be a string literal but you beat me to it – itodd Sep 07 '17 at 02:19
  • Yeah as far as what the innerHTML should be, I assumed the OP doesn’t want have `` – sideshowbarker Sep 07 '17 at 02:23
  • Anyway, I think the more typical way to do would be to use `attachShadow` in the `MyComponent` constructor, like this: 'const shadowRoot = this.attachShadow({mode: 'open'}); shadowRoot.innerHTML = \`

    header

    copy

    \`'. (Though you need to imagine the line breaks in that markup, because Stack Overflow eats them in comments.)
    – sideshowbarker Sep 07 '17 at 02:30
  • thanks @sideshowbarker. i am aware of the typical way of setting innerhtml in a shadow root. what im trying to figure out is how to use a template that isn't attached to the parent document so i can keep my component self contained. Maybe I should make a new question... – rakitin Sep 07 '17 at 12:22
  • @tim yeah a new question with that more-specific description would be good I think. But as far as the question you actually asked here, I think @itodd’s answer is a good response that will help others here at Stack Overflow who come across your question here in the future – sideshowbarker Sep 07 '17 at 12:44
  • @itodd is it necessary to have an actual document to attach to, or is this just using a static method of the document prototype? Anyway, here's a better question for what I'm trying to do - thanks for your help! https://stackoverflow.com/questions/46097077/how-to-stamp-out-template-in-self-contained-custom-elements-with-vanilla-js – rakitin Sep 07 '17 at 13:07