I’d like to create a custom element to render a select input.
One parent creates <select>
then a slot
generates the <option>
based on an array of choices.
import {html, css, LitElement} from 'lit';
export class SimpleSelect extends LitElement {
static properties = {};
constructor() {
super();
}
render() {
return html`<select><slot><option>None</option></slot></select>`;
}
}
customElements.define('simple-select', SimpleSelect);
export class SimpleOptions extends LitElement {
static properties = {
options: {type: Array},
};
constructor() {
super();
this.options = [];
}
render() {
let opts = this.options.map((el) =>
`<option value="${el.value}">${el.label}</option>`
);
return html`${opts.join("")}`;
}
}
customElements.define('simple-options', SimpleOptions);
<!DOCTYPE html>
<head>
<script type="module" src="./simple-greeting.js"></script>
</head>
<body>
<simple-select>
<simple-options options='[{"label":"A","value":"a"},{"label":"B","value":"b"},{"label":"C","value":"c"}]'></simple-options>
</simple-select>
</body>
This fails to render the slotted children; playground.
2
Answers
I don’t believe this is how Lit Element is designed to be used. Looking at the lit playground code you can see that the browser doesn’t render the component as options within a select object, it renders the two custom components:
Because LIT element uses shadowDOMs, the select component doesn’t have visibility into the option component.
You could probably use a query selector to manually extract the options from the simple-select, however, at that point why not just combine the components? Here is an example of the combined component
Why use Lit?
As said in the comments. It is a HTML limitation;
<option>
must be a direct child of<select>