javascriptcheckboxdom-eventsshadow-domcustom-element

How to listen for LightDOM Label "FOR=" events via ShadowDOM Custom Element


EDIT 1

@Danny (and everyone)

"Is there a reason your needs to be independent outside the Component? "

Please let me explain the use-case here. My custom-element ABC-TOGGLE is (wants to be) Label agnostic. Whether or not a LABEL tag is present is completely at the disgression of the LightDOM author/caller of my component. All I want/need to do is acknowledge the runtime environment/ambience and adapt accordingly.

Just as ABC-TOGGLE is agnostic to being part of a HTML FORM, yet will comply with either environment.

IMHO, (nah it's bleeding obvious) a click on a user-supplied LABEL FOR my Web Component MUST generate a click-event on #disTick.

If you are saying this is impossible or the specification rules it out then fine, please post link. Otherwise, what do I listen on?

END EDIT 1

How do I get a caller's HTML "Label" surrounding my Custom Element to bubble its "click" events to my shadow root? Is there not something in the shadowRoot that I can listen for Click events for my LightDOM label?

I believe this clicking labels answer comes close but I am inheriting from HTMLElement.

In the following code I want my ABC-TOGGLE custom element to hear events on label "aLabel".

export class ABCToggle extends HTMLElement 
{
    static formAssociated = true;

No joy (#toggle is the top level element): -

    this.#shadowRoot.host.addEventListener('click', (e) => {
        console.log("SR click");
    });
        
    this.#shadowRoot.addEventListener('click', (e) => {
        console.log("SR click");
    });
    this.#toggle.addEventListener('click', (e) => {             

Calling HTML: -

    <div id="disableIt">
    <label id="aLabel" for="disTick">Disable Toggle&nbsp;</label>
    <div id="tickContainer">
        <abc-toggle id="disTick" name="disTick" checked="false" tabindex=0 type="tick"></abc-toggle>
    </div>
</div>

Solution

  • OK, this is not actually a solution but more info so I'm sure one of you will get it!

    If you go to the demo you'll see that if you click on the LABEL

    <label for="disTick">Disable Toggle&nbsp;</label>
    

    then I can pick the click up in my custom element on shadowRoot.host but I can't distinguish between a Click on "disTick" and a click on it's label-for.

    I guess I could stopPropagation on the CLICK event in my custom element and create a custom event to differentiate but it's all getting messy :-(

    Any alternatives?

    EDIT 1

    The answer is to get the composedPath on the Custom Element's shadowRoot.host.onclick event and and if element[0] is not this.#checkbox (in my case) then a light DOM label was clicked (or host.click() was called) so I just this.#toggle.click(). I think

    EDIT 2

    Works like a charm

            this.#shadowRoot.host.addEventListener("click", (e) => {
            if (e.composedPath()[0] != this.#checkbox)
                this.#toggle.click();
        });