So I have code that's something like this:
<template id="cool-btn-template">
<script>
const button = document.getElementById('click-me');
button.addEventListener('click', event => alert(event));
</script>
<style>
#click-me {
all: unset;
background: tomato;
border: 0;
border-radius: 4px;
color: white;
font-family: Helvetica;
font-size: 1.5rem;
padding: .5rem 1rem;
}
</style>
<button id="click-me">Log click event</button>
</template>
<cool-btn></cool-btn>
<script>
class CoolBtn extends HTMLElement {
constructor() {
super();
const template = document.getElementById('cool-btn-template');
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(template.content.cloneNode(true));
}
}
customElements.define('cool-btn', CoolBtn);
</script>
If you run the code, you'll notice that document
in the template's script tag refers to the overall document, not the shadowDom. How do I make document
mean its shadowDom?
I believe all JavaScript for a custom element is meant to go inside its class, which is how you scope it to the element:
<template id="cool-btn-template">
<style>
#click-me {
all: unset;
background: tomato;
border: 0;
border-radius: 4px;
color: white;
font-family: Helvetica;
font-size: 1.5rem;
padding: .5rem 1rem;
}
</style>
<button id="click-me">Log click event</button>
</template>
<cool-btn></cool-btn>
<script>
class CoolBtn extends HTMLElement {
constructor() {
super();
const template = document.getElementById('cool-btn-template');
const shadowRoot = this.attachShadow({mode: 'open'});
shadowRoot.appendChild(template.content.cloneNode(true));
shadowRoot.getElementById('click-me').addEventListener('click', event => alert(event))
}
}
customElements.define('cool-btn', CoolBtn);
</script>