In my app, I do an html import from A
to a file B
which has this. But it alerts null. If I open B
directly in the browser, it alerts the template HTML dom element. How can this happen, which this same code pretty much is from google own documents for web components https://developers.google.com/web/fundamentals/architecture/building-components/customelements.
<template id="x-foo-from-template">
</template>
<script>
alert(document.querySelector('template'));
</script>
This is googles example:
<template id="x-foo-from-template">
<style>
p { color: orange; }
</style>
<p>I'm in Shadow DOM. My markup was stamped from a <template>.</p>
</template>
<script>
customElements.define('x-foo-from-template', class extends HTMLElement {
constructor() {
super(); // always call super() first in the ctor.
let shadowRoot = this.attachShadow({mode: 'open'});
const t = document.querySelector('#x-foo-from-template');
const instance = t.content.cloneNode(true);
shadowRoot.appendChild(instance);
}
...
});
</script>
Thanks
Two factors to take into consideration when importing a file that contains a script
, and a template
:
script
will execute at import time, while markup and other resources need to be added to the main page explicitly
An import link doesn't mean "#include the content here". It means "parser, go off an fetch this document so I can use it later". While scripts execute at import time, stylesheets, markup, and other resources need to be added to the main page explicitly.
window.document
refers to the main page document, not the template document.This should explain why your script alerts null
. Because the script is executed immediately, while the template hasn't been added to the main page yet.
You can create a reference to the import document itself where the template
can be found.
// importDoc references this import's document
var importDoc = document.currentScript.ownerDocument;
alert(importDoc.querySelector('template'));
Or, you can query the main document after you insert the template into the document:
var import = document.querySelector('link[rel="import"]').import;
var template = import.querySelector('template');
// Append template to main document
document.head.appendChild(template);
// Now you can query the main the document
alert(document.querySelector('template'));
In response to the question in the comment below:
In Google's example, the call to document.querySelector()
is found in the constructor function of the custom element. The constructor function is called when the element is instantiated. Therefore, the element already exists in the main page when this code is run.