Reputation: 87
I am trying to raise events out of a webcomponent, but it does.
<my-component id="xyz" bez="hallo" hello="myScript()"></my-component>
<script>
xyz.addEventListener("hello", function(event) {
console.log(event.detail.name);
});
</script>
Neither the html-tag "hello" does raise the event, nor the event-listener does.
The web component looks like this:
var button=document.createElement("button");
button.innerHTML=cap;
button.addEventListener('click', () => {
console.log("click");
button.dispatchEvent(new CustomEvent("hello", {
detail: { name: "John" }
}));
});
shadow.appendChild(button);
Can anyone help me please to find the mistake? Thanks a lot.
Code-Fiddle here: https://jsfiddle.net/b43uqsLp/2/
Upvotes: 8
Views: 4637
Reputation: 21301
There is some information missing in the other answer
click
listener is inside shadowDOM, so composed
has no useclick
are not stopped by shadowDOMcomposed:true
and bubbles:true
to escape Custom Elements with 'open' shadowDOM.connectedCallback
unless you are 100% certain that is what you want; the connectedCallback
runs again when DOM elements are moved in the documentsuper()
returns and sets the 'this', and attachShadow()
returns and sets the this.shadowRoot
reference, no need to use your own variables.This JSFiddle: https://jsfiddle.net/CustomElementsExamples/qody0u4n/
shows composed
and bubbles
behaviour, with extra listeners on the document
document.addEventListener("click", (evt) => log(evt, 'document'));
document.addEventListener("MyEvent", (evt) => log(evt, 'document'));
<my-component id=ONE></my-component>
<my-component id=TWO composed>
<my-component id=INSIDETWO composed></my-component>
</my-component>
<my-component id=THREE composed bubbles>
<my-component id=INSIDETHREE composed bubbles></my-component>
</my-component>
notes
none of the MyEvents are caught by element ONE or the document
The document only receives the CustomEvent("MyEvent")
when both composed
and bubbles
are set
The composed
event does not stop at the shadowRoot boundary! It is halted at the Custom Element boundary. In the JSfiddle there are additional DOMlisteners
on my-component
to demonstrate this.
Also see: https://pm.dartus.fr/blog/a-complete-guide-on-shadow-dom-and-event-propagation/
Upvotes: 5
Reputation: 16412
The problem occurs because of the Shadow DOM (try to inspect your component and you will see what I mean):
Good news, it's really simple to fix - just propagate the event across the shadow DOM into the regular DOM via composed: true
property in your CustomEvent's options:
button.dispatchEvent(new CustomEvent("hello", {
detail: { name: "John" },
composed: true // Like this
}));
Here is JSFIDDLE.
Upvotes: 4