Events that Cross Shadow DOM Boundary
Web Components ⟩ Shadow DOM ⟩ Events ⟩
JS.info ⟩ Custom events in shadow DOM
Google ⟩ The Shadow DOM event model
The events that do cross the shadow boundary are:
category
events
focus
blur, focus, focusin, focusout
mouse
click, dblclick, mousedown, mouseenter, mousemove, ...
wheel
wheel
input
beforeinput, input
keyboard
keydown, keyup
composition
compositionstart, compositionupdate, compositionend
drag
dragstart, drag, dragend, drop, ...
Built-in Events
Custom Events
If composed: false (default), consumers won't be able to listen for the event outside of your shadow root.
// attach shadow root (⭐️ so outer's light DOM is not shown)
outer.attachShadow({mode: 'open'});
let inner = document.createElement('div');
outer.shadowRoot.append(inner);
/*
div#outer
#shadow-dom
div#inner
*/
// ⭐️ listen for 'test' event
document.addEventListener('test', e => log(lightDOM, e.detail));
outer.shadowRoot.addEventListener('test', e => log(shadowDOM, e.detail));
// ⭐️ composed custom event
function sendComposedEvent(){
inner.dispatchEvent(new CustomEvent('test', {
bubbles: true,
composed: true, // ⭐️ composed
detail: "'composed' event from inner <div>"
}));
}
// ⭐️ not composed custom event
function sendNonComposedEvent(){
inner.dispatchEvent(new CustomEvent('test', {
bubbles: true,
composed: false, // ⭐️ not composed
detail: "not composed"
}));
}
// ⭐️ escape HTML special characters
String.prototype.escapeHTML = function () {
return this
.replace(/&/g, '&' ) // ampersand (must be first❗️)
.replace(/>/g, '>' ) // greater than
.replace(/</g, '<' ) // less than
.replace(/"/g, '"') // double-quote
.replace(/'/g, ''' ) // single-quote
.replace(/`/g, '`' ); // backtick
}
// log
function log(dom, msg) {
dom.innerHTML += msg.escapeHTML() + '<br>';
}<!-- ⭐️ element with shadow DOM -->
<div id="outer">outer div</div>
<div id="buttons">
<button onclick="sendComposedEvent()">composed event</button>
<button onclick="sendNonComposedEvent()">non-composed event</button>
</div>
<!-- console log -->
<div id="lightDOM" class="output">
<p>Light DOM event logs:</p>
</div>
<div id="shadowDOM" class="output">
<p>Shadow DOM event logs:</p>
</div>.output {
border: 1px solid black;
padding: 8px;
background: black;
color: white;
}
.output p {
margin: -8px;
margin-bottom: 8px;
padding: 8px;
background: tomato;
}
#lightDOM p {
background: hsl(225, 80%, 60%);
}
#buttons {
margin-bottom: 8px;
}Last updated
Was this helpful?