So I'm using a jQuery plugin under shadowRoot in my app. The HTML is as follows
#shadow-root
<div id="container">
<div class="display-item">Item 1</div>
<div class="display-item">Item 2</div>
<div class="display-item">Item 3</div>
<div class="display-item">Item 4</div>
</div>
I want to attach event listeners to the divs with class = "display-item" for events like mousedown,mousedown,focus. I tried the following:
let root = document.getElementById(divID).shadowRoot;
$(root).on('mousedown', '#container div.display-item', function(event) {
//function
});
But this doesn't work. How could I make this work?
EDIT :
I also tried this approach, something like $('#container .display-item'), but it wouldn't work since it's looking for those elements under document I believe and it wouldn't find them since they're under the shadow DOM,so I have to use the root as pivot. Is there an equivalent of jquery 'find' method where I can query like multiple elements with the same class, using the shadow root as pivot? That way, I can attach event listeners to the individual elements explicitly.
In the ideal world Web Components should care about the "outside" world,
and most of all the Outside should not be dependent on Web Components inner
world.
That means the Component should take care of attaching listeners.
Since you are in control what the Component does, there is no need for addEventListener
(allowing for multiple same listeners)
customElements.define("my-component", class extends HTMLElement {
constructor() {
super().attachShadow({mode: "open"})
.innerHTML = `<div id="container">
<div class="display-item">Item 1</div>
<div class="display-item">Item 2</div>
<div class="display-item">Item 3</div>
<div class="display-item">Item 4</div>
</div>`;
}
listen() {
this.shadowRoot.querySelectorAll('.display-item').forEach(div => {
div.onclick = (evt) => {
document.body.append(div.innerText);
}
});
this.listen = () => console.warn("ran attach listener once");
}
})
<my-component id=COMP></my-component>
<script>
window.onload=()=>{
document.querySelector("#COMP").listen();
}
</script>
Note: IE9 was the last browser to implement JS queryselectors... in 2011
If you are only using jQuery for its $()
, you have burdened your clients with a not required 80KB+ download for the past 11 years.
If you really want to touch the Inside World
document.querySelector("#COMP").shadowRoot.querySelectorAll('.display-item').forEach
does the trick, but breaks when there are more shadowRoots in between.
And in my world I don't tell Components what to do,
I make Components listen:
window.onload=()=>{
document.dispatchEvent("LISTEN");
}