1

Basically, I want to querySelect a <template> from javascript and I keep getting null.

JavaScript file:

    class MyImportWebcomponent extends HTMLElement {
        constructor() {
            super();
        }
        connectedCallback() {
            const shadowRoot = this.attachShadow({ mode: "open" });
            const template = document.querySelector("my-import-webcomponent-template");
            const instance = template.content.cloneNode(true);
            shadowRoot.appendChild(instance);
        }
    }

customElements.define("my-import-webcomponent", MyImportWebcomponent);

Template object from my vanilla webcomponent

<template id="my-import-webcomponent-template">
  <div id="mydiv" name="mydiv">
    <p>Trying html importing another javascript file</p>
  </div>
</template>

<script src="/to-try/my-import-webcomponent.js"></script>

index.html

<my-import-webcomponent></my-import-webcomponent>
<link rel="import" href="./to-try/my-import-webcomponent.html" />

The main issue is that document.querySelector("my-import-webcomponent-template") returns undefinied.

IN case it adds something usefull, if I try keep both javascript and html in same file and instead of querySelector I create straight the element, I successfully can do it.

All in a single file

const templateString = `<div id="mydiv" name="mydiv"><p>Trying html plus javascript in same file</p></div>`;
const template = document.createElement("template");
template.innerHTML = templateString;

export class MyCompleteWebcomponent extends HTMLElement {
    constructor() {
        super();
        const shadowRoot = this.attachShadow({ mode: "open" });
        shadowRoot.appendChild(template.content.cloneNode(true));
    }
}
customElements.define("my-complete-webcomponent", MyCompleteWebcomponent);

My question would be exact the same as queryselector if it wasn't for two reasons: (1) they seemed to rely on Polifys which it isn't my case and (2) the answer accepted is based on document.currentScript.ownerDocument which demands an old library as far as I know.

*** edited after suggestion to use instead of

<!-- <link rel="import" href="./to-try/my-import-webcomponent.html" /> -->
<script type="module" src="./to-try/my-import-webcomponent.js"></script>
<my-import-webcomponent></my-import-webcomponent>

Nothing changed at all

*** edited after recommended to add "#". No changes at all

enter image description here

Jim C
  • 3,957
  • 25
  • 85
  • 162
  • 1
    [HTML Imports](https://developer.mozilla.org/en-US/docs/Web/Web_Components/HTML_Imports) are obsolete and shouldn't be used in new code. – Herohtar Aug 07 '19 at 20:33
  • thanks. Looking at my above example, kindly, how would you approach assuming you MUST separate html from javascript file and you CAN'T use extranal libraries (eg. Polymer)? – Jim C Aug 07 '19 at 21:18
  • well, and how do I fix the issue posted above (... document.querySelector("my-import-webcomponent-template") returns undefinied...)? Additionally, replacing by – Jim C Aug 07 '19 at 21:45
  • It's not entirely clear which code is in which file and how you are using it. It would be helpful if you edited your code snippets into a [mcve], and indicated the names of the files that the code belongs to. – Herohtar Aug 07 '19 at 21:54
  • as far as I can see it is very clear which content belongs a each file. On top of each code snippet there is the file name or a phrase which clear mentioned it is a separated file (have you heard about Webcomponets? The phrase "...my vanilla webcomponent" should make sense. I get "null" when I try "document.querySelector("my-import-webcomponent-template")" from a javascript which is imported to a html file via – Jim C Aug 08 '19 at 15:21
  • 1
    Also, I just noticed something: `document.querySelector("my-import-webcomponent-template")` is trying to select an *element* named "my-import-webcomponent-template", you should be using `document.querySelector("#my-import-webcomponent-template")` if you're using the ID. – Herohtar Aug 08 '19 at 15:27
  • Chrome. There is no difference with/without "#". I added a picture. If you want you can clone the code. In to-try folder there are three tentatives to separate javascript from html files. And the one mentioned above just return null for document.querySelector("#my-import-webcomponent-template"); Source at https://github.com/jimisdrpc/skyscanner-webcomponents/tree/master/public/to-try – Jim C Aug 08 '19 at 17:08
  • 1
    Yeah, I see it doesn't work even with that fixed. Unfortunately, I'm not sure how that method is supposed to work since I've only used the current version of custom elements. My suggestion would be to take a look at how to use Custom Elements v1 and see if you can achieve what you want there. This method isn't going to be much use to you because only Chrome supports HTML Imports and even they will be removing it in version 80 (some time around Feb 2020). – Herohtar Aug 08 '19 at 17:23
  • 1
    In fact, if you're using a current version of Chrome and look at your console while loading your page you should see the following message: *"[Deprecation] HTML Imports is deprecated and will be removed in M80, around February 2020. Please use ES modules instead. See https://www.chromestatus.com/features/5144752345317376 and https://developers.google.com/web/updates/2019/07/web-components-time-to-upgrade for more details."* – Herohtar Aug 08 '19 at 17:24
  • 1
    If you get ``null`` the element is not (yet) in the DOM. First verify your content actually IS in the DOM at one point by delaying your code in the connectedCallback with a setTimeout , then work backwards to find the cause of your issue. Reproducing your problem with runable code here in SO in JSFiddle, StackBlitz or CodePen will help (and challenge) people to dig into your problem. Github is not runable.. no-one (well not me) is going to pick up your code from there and make it work – Danny '365CSI' Engelman Aug 08 '19 at 18:39

1 Answers1

1

If you want to load HTML files with <link rel="import"> then you'll need to load the HTML Imports library before.

<script src="https://raw.githubusercontent.com/webcomponents/html-imports/master/html-imports.min.js"></script>
<link rel="import" href="./to-try/my-import-webcomponent.html">
...
Supersharp
  • 29,002
  • 9
  • 92
  • 134
  • I read from above github "This platform feature, and polyfill, is deprecated, please consider using ES Modules instead." How would you "import" via ES Modules JavaScript file to the HTML file mentione above? Kindly, take a notice that I have already tried such suggestion without success. As mentioner under "*** edited after suggestion to use instead of" I have tried without success " " – Jim C Aug 14 '19 at 14:17
  • 1
    You cannot import HTML directly with ES6 import. What you tried won't work because you load the JS file, but from inside it you never load the HTML file. You should use fetch to load the HTML. – Supersharp Aug 14 '19 at 15:15