Saltar al contenido

QuerySelector no encuentra la plantilla en la importación de HTML

Te damos la bienvenida a nuestra página web, ahora vas a hallar la resolución a lo que necesitas.

Solución:

En el

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.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 4)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *