class RealTodo extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: "open", slotAssignment: "manual" });
}
connectedCallback() {
const todoTemplate = document.getElementById("todo_template");
const todoApp = todoTemplate.content.cloneNode(true);
this.shadowRoot.appendChild(todoApp);
const slot = this.shadowRoot.querySelector("slot");
console.log(slot);
const li = document.createElement("li");
li.textContent = "Buy food";
slot.assign(li);
}
}
customElements.define("real-todo", RealTodo);
<template id="todo_template">
<h1>TODO LIST</h1>
<ol>
<slot></slot>
</ol>
</template>
<real-todo></real-todo>
I try to assign content inside shadowDom's slot manually. It doesn't assign. No error show. I tested in firefox, chrome.
According to spec slot.assign(nodes);
will assign inside slotAssignment: "manual"
shadowdom
Your const li = document.createElement("li");
creates a Node in memory
SLOTElement.assign()
only accepts existing DOM Element(s) in
first level lightDOM
And you don't want to use append[Child]()
, because that moves a DOM Element
customElements.define("real-todo", class extends HTMLElement {
constructor() {
const button = (props) => Object.assign(document.createElement("button"),props);
super()
.attachShadow({mode: "open", slotAssignment: "manual" })
.append(
button({ innerHTML:"Food" , onclick : e => this.showlist("food") }),
button({ innerHTML:"Animals", onclick : e => this.showlist("animal") }),
document.getElementById(this.nodeName).content.cloneNode(true)
);
}
connectedCallback(){
this.showlist();
}
showlist( list=this.getAttribute("list") ){
this.shadowRoot.querySelector("span").innerHTML = list;
const li = this.querySelectorAll(`li[list*="${list}"]`);
this.shadowRoot.querySelector("slot").assign(...li);
}
});
<template id="REAL-TODO">
<h1>A <span></span> list</h1>
<ol>
<slot></slot>
</ol>
</template>
<real-todo list="animal">
<li list="animal">Cat</li>
<li list="animal">Dog</li>
<li list="food">Pie</li>
<li list="food">Beer</li>
<li list="food">Pizza</li>
<li list="animal,food">Chicken</li>
<div>
<li list="animal,food">Never listed!!</li>
</div>
</real-todo>
LI
elements are slotted: