'WebComponents: how to get the resolved value of a slot in shadow DOM?
I have a web component and I want to adjust the value of its slot.
Unfortunately, I am unable to get the resolved value from it.
How can I do that?
const template = document.createElement('template');
template.innerHTML = `
<p><slot></slot></p>
`;
class MyComp extends HTMLElement {
constructor() {
super();
this.root = this.attachShadow({mode: 'open'});
this.root.appendChild(template.content.cloneNode(true));
}
connectedCallback() {
const slot = this.shadowRoot.querySelector('slot');
console.log('VALUE:', slot.innerText); // always empty
}
}
customElements.define('my-comp', MyComp);
<my-comp>abc</my-comp>
Solution 1:[1]
You can assign an EventListener to watch for SLOT changes
MDN Documentation
customElements.define('my-element', class extends HTMLElement {
constructor() {
super();
this.attachShadow({
mode: 'open'
}).appendChild(document.getElementById(this.nodeName).content.cloneNode(true));
}
connectedCallback() {
this.listeners = [...this.shadowRoot.querySelectorAll("SLOT")].map(slot => {
let name = "slotchange";
let func = (evt) => {
let nodes = slot.assignedNodes();
console.log(`Slot ${slot.name} changed to ${nodes[0].outerHTML}`)
}
slot.addEventListener(name, func);
return () => slot.removeEventListener(name, func); // return cleanup function!!!
})
}
disconnectedCallback() {
this.listeners.forEach(removeFunc => removeFunc());
}
});
<template id="MY-ELEMENT">
<style>
::slotted(*) {
background: yellow;
margin: 0;
}
::slotted(span) {
color: red;
}
</style>
<b>
<slot name=title></slot>
</b>
<slot name=content></slot>
</template>
<my-element>
<span slot="title">Hello World</span>
<p slot="content">What a wonderful day!</p>
</my-element>
<my-element>
<span slot="title">Hello Tomorrow</span>
<p slot="content">What will you bring?</p>
</my-element>
JSFiddle: https://jsfiddle.net/CustomElementsExamples/vu9w1zyx/
Solution 2:[2]
Less code, easier to understand. For simple templates I'd rather create the elements programmatically, then add a slotchange
listener:
class MyComp extends HTMLElement {
p = document.createElement('p');
slot = document.createElement('slot');
constructor() {
super();
this.p.append(this.slot);
this.attachShadow({mode: 'open'}).append(this.p);
this.slot.addEventListener('slotchange', () => console.log('VALUE:', this.slottedValue))
}
get slottedValue() { return this.slot.assignedNodes()[0].wholeText }
}
customElements.define('my-comp', MyComp);
console.log(document.querySelector('my-comp').slottedValue);
<my-comp>abc</my-comp>
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | |
Solution 2 | connexo |