DEV Community

Discussion on: Web Component developers do not connect with the connectedCallback (yet)

Collapse
 
dannyengelman profile image
Danny Engelman • Edited

readystatechage will not work

Here is a full working JSFiddle: jsfiddle.net/WebComponents/d9sbzcex/

Extract of your solution:

    customElements.define("your-component", class extends BaseClass {
        connectedCallback() {
            LOG("Init", this); // Empty innerHTML
            if (document.readyState == "loading") {
                document.addEventListener("readystatechange", () => {
                    LOG("Access", this); // Hello World!
                }, {
                    once: true
                })
            }
        }
    });
Enter fullscreen mode Exit fullscreen mode

Issues

  • (minor) You can not call this.connectedCallback in the handler, it will have the wrong lexical scope. so a .bind(this) is required

  • But you can't just run connectedCallback again because it would run any other (initialization) code again also So I changed your code as above

Code now runs fine

Although your workaround runs "late" after the readystatechange Event

But now another issue occurs

Because your code relies on an Event that happens only once, that code will never fire again.

So if you move DOM around, or append DOM, that Event will never fire.

Your component never did the "Access" again

Collapse
 
darkwiiplayer profile image
𒎏Wii 🏳️‍⚧️

That isn't my work-around though. Here's what that should look like:

customElements.define("your-component", class extends BaseClass {
    connectedCallback() {
        if (document.readyState === "loading") {
            return document.addEventListener("readystatechange", this.connectedCallback.bind(this), {once: true})
        }
        LOG("Access", this); // Hello World!
    }
});
Enter fullscreen mode Exit fullscreen mode

When the component is loaded before the DOM is fully loaded, it will defer its connectedCallback to the next readystatechange event by attaching an event listener and returning early, but when the DOM has already loaded, it will jump over the early return and do its initialisation as usual.

This works in all three cases:

  • When the component is defined before the DOM finishes loading (via the event handler)
  • When the component is defined after the DOM finishes loading (skipping the early return)
  • When the component is inserted via javascript (again, skipping the early return)