I have a web component custom element defined like so.
It not possible to do it like that because the parent element of an <option>
tag must be a <select>
tag. So you can use with Shadow DOM because the <slot>
element will break the parent/child hierachy.
Solution 1 : move elements
A workaround is to move the content of the light DOM inside the <select>
element in the template.
class Dropdown extends HTMLElement {
constructor() {
super()
const shadowRoot = this.attachShadow( {mode: 'open'} )
let template = document.getElementById( 'dropdown-template' )
shadowRoot.appendChild( template.content.cloneNode(true) )
const select = shadowRoot.querySelector( 'select' )
shadowRoot.addEventListener( 'slotchange', ev => {
let node = this.querySelector( 'option' )
node && select.append( node )
} )
}
}
customElements.define("drop-down", Dropdown);
<template id="dropdown-template">
<select></select>
<slot></slot>
</template>
<drop-down>
<option>one</option>
<option>two</option>
<option>three</option>
</drop-down>
Solution 2: customized <select>
Another possibility is to avoid Shadow DOM and define your drop-down list as a customized built-in <select>
element. Maybe this won't fit your needs if you want to customize the layout.
<select is="drop-down">
<option>one</option>
<option>two</option>
<option>tree</option>
</select>