Te damos la bienvenida a nuestra página web, ahora vas a hallar la resolución a lo que necesitas.
Solución:
En el s inside the imported HTML, don't use
document.querySelector(...)
.
Use:
// while inside the imported HTML, `currentDocument` should be used instead of `document`
var currentDocument = document.currentScript.ownerDocument;
...
// notice the usage of `currentDocument`
var templateInsideImportedHtml = currentDocument.querySelector('#template');
Example (fixing the example in the question):
var currentDocument = document.currentScript.ownerDocument; // <-- added this line
class WZView extends HTMLElement
createdCallback ()
var root = this.createShadowRoot();
var template = currentDocument.querySelector('#template'); // <-- changed this line
root.appendChild(document.importNode(template.content, true));
Compatibility:
Only IE 11 won't support it. Most browsers (including Edge) implement it, and for IE 10 and below there is a polyfill.
Update: My original answer is garbage. My problem was that I was trying to obtain the currentScript.ownerDocument
from a method inside the class, instead of in a script actively running in the current document (e.g., in an IIFE where I define the class and, hence, where the script would be running alongside of the template). A method may be called from another script, the "currentScript" at that point (i.e., possibly a different document altogether, especially if you're importing from other imports, like I was).
So this is bad:
class Foo extends HTMLElement
constructor()
const template = document.currentScript.ownerDocument.querySelector("template");
// do something with `template`
and this is better:
(() =>
const _template = document.currentScript.ownerDocument.querySelector("template");
class Foo extends HTMLElement
constructor()
// do something with `_template`
)();
Hopefully that helps someone else who is dumb like me.
Original answer:
I also encountered problems trying to gain access to templates from an import hierarchy of some depth. The currentScript
suggestion didn't work for me in this case: in Chrome/Chromium, the currentScript
always referred to the first import, but never to any of the deeper imports (as I mentioned in a comment to @acdcjunior's answer), and in Firefox (via polyfill), the currentScript
was null
.
So what I ended up doing was something similar to @Caranicas's answer. I created a utility function that finds the imported file, call it once outside of the class in an IIFE, and then made it a property of the class, like this:
index.html:
var _resolveImport = function(file)
return (function recur(doc)
const imports = doc.querySelectorAll(`link[rel="import"]`);
return Array.prototype.reduce.call(imports, function(p, c) (
~c.href.indexOf(file)
? c.import
: recur(c.import)
);
, null);
)(document);
src/app.html:
...
src/componente.html:
...
_resolveImport
es costoso, por lo que es una buena idea no llamar a esto más de una vez para cada importación, y solo para las importaciones que realmente lo necesitan.
Comentarios y puntuaciones de la guía
No se te olvide difundir esta división si te fue útil.