0

I want to be able to have an event that calls an asynchronous function that (1) fetches a simple web component and (2) adds the customElement to a container (div id).

Using the fetch API, I haven't had any success. Among a lot of tests I tried to convert "result.text()" to HTML with new DOMParser and a [Object HTML] appears in the targeted container or I tried to convert "result.text()" to a function and I get [Object Promise]...

This is currently my load function

async function load(){
    var object = fetch("./src/pages/product.js")
            .then(result => result.text())
            .then(obj => new Function(obj))
            .then(t => console.log(t));
    container.innerHTML = object;
}

This is my customElement:

class MyTest extends HTMLElement {
    constructor() {
        super()

        const pElem = document.createElement("p");
        pElem.textContent = "Hello from my-test component";

        const shadowRoot = this.attachShadow({mode: "open"});
        shadowRoot.appendChild(pElem);
    }

}

customElements.define("my-test", MyTest);

The expected result is the display of "Hello from my-test component" in the container. How would you do it?

Your help will be very appreciated! Thank you!

Student
  • 135
  • 2
  • 13

2 Answers2

2

Typo...

When you create a customElement like this: (shortened way, thanks to Danny)

customElements.define("my-test", class extends HTMLElement {
    constructor() {
        super()
           .attachShadow({mode:"open"})
           .appendChild(document.createElement("p"))
           .textContent = "Hello from my-test component";
    }
})

You can asynchronously call it this way:

async function load() {
    const imported = await import("./pages/product.js");
    const customElem = document.createElement("my-test"); 
    container.appendChild(customElem);
}

I hope this will someone!

Student
  • 135
  • 2
  • 13
0

Nothing wrong with your element code (in product.js I presume)

You need to properly load that JavaScript file

All answers here: How do I include a JavaScript file in another JavaScript file?
(with 4400+ upvotes, give him one more)


You can shorten your code:

customElements.define("my-test", class extends HTMLElement {
    constructor() {
        const pElem = document.createElement("p");
        pElem.textContent = "Hello from my-test component";
        super().attachShadow({mode: "open"}).append(pElem);
    }
})
  • because super returns this
  • and attachShadow both sets and returns this.shadowRoot
  • append is shorter and can take multiple parameters, but does not return anything
  • appendChild returns the inserted element, so you could write:
customElements.define("my-test", class extends HTMLElement {
    constructor() {
    super()
      .attachShadow({mode:"open"})
      .appendChild(document.createElement("p"))
      .textContent = "Hello from my-test component";
    }
})
Danny '365CSI' Engelman
  • 16,526
  • 2
  • 32
  • 49
  • Sorry, I have read the linked page and, except the FetchInject, it does not seem to answer my question. I try to do it with native/direct code, to learn Javascript. Thank you fo shortening my code. I think the first line should read `customElement.define("my-test", class extends HTMLElement {` – Student May 24 '20 at 07:43
  • For now I'm heading toward something (does work yet) like this: `async function load() { const imported = await import("./pages/product.js"); customElements.define("my-test", imp.MyTest()); const cutomElem = document.createElement("my-test"); container.appendChild(customElem); }` Something doesn't work in line 3 (custmonEl....). Still searching, any help is welcome! – Student May 24 '20 at 07:50