Search code examples
javascripthtmltemplatesweb-component

Import <template> Element From Another Website


tl;dr: Trying to get <template> element hosted somewhere else, how do?


I have an html page locally, which has the following template in the <head> (The point is that it's some stuff within a template tag):

  <template>
    <style>div{ background-color: red;}</style>
    <div id = "testTemplate">1</div>
  </template>

As expected, this code doesn't template until I attach the template to some shadow-root, e.g.:

<script>
  var template = document.querySelector('template');
  var containerHost = document.querySelector('.containerHost');
  var shadowRoot = containerHost.createShadowRoot();
  shadowRoot.appendChild(document.importNode(template.content, true));
</script>

When I run the code above, my template displays. Great. Now I am trying to move my web component to a website hosted somewhere else. So I created a github page that I confirmed works: https://myusername.github.io/webcomponent/.

That is a complete html page, that has my template (same as above) in the head. I then try to pull in the html from the github page into my html using:

  <link rel="import" href="https://myusername.github.io/webcomponent/">

This throws no errors, but the <template> is NOT visible to my page and I get the following error:

Uncaught TypeError: Cannot read property 'content' of null at web-component2.html:31

Because var template = document.querySelector('template'); returns null.

What gives? How do I get to my template?

P.S. Using this page as a guide
Got the html import statement from here


Edit:

I see a request going out to my site and coming back with a 304, this is the response:

<html>
<head>

  <template>
    <style>div{ background-color: red;}</style>
    <div id = "testTemplate">1</div>
  </template>

</head>
<body>
</body>
</html>

So the html I expect comes back fine (but is not accessible from my local page) - I am not sure if I need to isolate the <template> or am missing something equally simple.


Solution

  • In case the linked article about imports goes away: once your imported content is fetched, you have to grab the content from the <link> element, not from document:

    function getTemplate(e) {
      let template = e.target.import.querySelector("template");
      shadowRoot.appendChild(document.importNode(template.content, true));
    }
    ...
    
    <link rel=import href="http://what.ever" onload="getTemplate(event)">
    

    for example. The <link> element has an "import" property that serves as the root of the document that's been imported, and you can then use querySelector() (and presumably other document style APIs) to dig around and find stuff in what was imported.