javascriptconstructorweb-componentlifecyclecustom-element

Obtain this.textContent during Custom Element Construction


This is a conceptual question for those who understand custom elements without seeing concrete code examples.

I'm creating a custom element that's display depends on its textContent. In the custom element's constructor, if I try to access this.textContent it returns an empty string, even though the html of that custom element does indeed contain text.

In order to obtain the textContent during the custom element's construction, I enclosed my constructor code within a setTimeout and then was able to make my custom elements construction be base on its textContent.

However, this felt a little hacky and I figured there was a more proper way to obtain textContent during an element's construction. That's when I found Using the life Cycle Callbacks.

The connectedCallback method allowed me to see textContent without putting a setTimeout into the custom element's constructor. However, this quote concerns me:

connectedCallback: . . . may happen before the element's contents have been fully parsed.

This worries me that if I have a lot of content inside the custom element, this.textContent may still return an empty string because all that text may not yet be "fully parsed".

Is this worry justified? Is there a more sure way to obtain this.textContent as a basis for your custom element's construction? Or, should I go with my initial solution of putting a setTimeout within the custom element's constructor?


Solution

  • 4 year later blogpost:

    https://dev.to/dannyengelman/web-component-developers-do-not-connect-with-the-connectedcallback-yet-4jo7


    In your example textContent is DOM content

    The constructor should not (try to) access DOM,
    as it can be run from .createElement('your-element') when there is no DOM at all.
    (or in a Server-Side-Rendering scenario)

    connectedCallback runs before the whole DOM inside finished parsing. If you want to access its DOM content you have to wait till Element DOM is ready.

    Only in FireFox you can access Element DOM content;
    see: wait for Element Upgrade in connectedCallback: FireFox and Chromium differences

    For detailed analysis see: https://jsfiddle.net/CustomElementsExamples/n20bwckt/
    Note the difference when run in FireFox and Chrome.

    setTimeout( func , 0 )

    is totally valid (but better not in the constructor) and ensures your code runs when the EventLoop is empty, thus when all DOM is ready to be accessed. You could also use requestAnimationFrame.
    All libraries do something similar under the hood to add updateComplete and the likes.
    With bare-bones Custom Element API you have to write it yourself.

    Note: The connectedCallback now triggers code that runs after a (potential) disconnectedCallback, so check for that with this.isConnected in your code.

    For visual diagram when all callbacks run see:
    https://andyogo.github.io/custom-element-reactions-diagram/

    Note: if you don't specify any methods in your own Element, the methods from HTMLElement run.
    So Elements without any declared constructor or connectedCallback are perfectly valid.
    In IconMeister I only use attributeChangedCallback