-
-
Save pmdartus/cd490a82617e025a2e73f79f7f9888b3 to your computer and use it in GitHub Desktop.
Scoped slot allocation and shadow DOM
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Scoped slot with declarative allocation</title> | |
</head> | |
<body> | |
<x-list></x-list> | |
<script> | |
customElements.define( | |
"x-list", | |
class extends HTMLElement { | |
#values = []; | |
#tmpl; | |
constructor() { | |
super(); | |
const shadowRoot = this.attachShadow({ | |
mode: "open", | |
}); | |
this.shadowRoot.innerHTML = `<div></div>`; | |
} | |
set template(tmpl) { | |
this.#tmpl = tmpl; | |
this.#rerender(); | |
} | |
get template() { | |
return this.#tmpl; | |
} | |
set values(v) { | |
this.#values = v; | |
this.#rerender(); | |
} | |
get values() { | |
return this.#values; | |
} | |
#rerender() { | |
if (!this.#tmpl || !this.#values) { | |
return; | |
} | |
const container = this.shadowRoot.querySelector("div"); | |
const slots = []; | |
// Remove all the slots | |
while (container.firstChild) { | |
container.firstChild.remove(); | |
} | |
// Remove all the existing children | |
while (this.firstChild) { | |
this.firstChild.remove(); | |
} | |
// Render all the slots | |
for (let i = 0; i < this.#values.length; i++) { | |
const slot = document.createElement("slot"); | |
slot.name = `__scoped-${i}`; | |
slots.push(slot); | |
container.appendChild(slot); | |
} | |
// Render all the scoped slotted content. | |
for (let i = 0; i < this.#values.length; i++) { | |
const tmpElm = document.createElement("template"); | |
tmpElm.innerHTML = this.#tmpl(this.#values[i]); | |
this.appendChild(tmpElm.content); | |
this.lastChild.setAttribute('slot', slots[i].name); | |
} | |
} | |
} | |
); | |
const list = document.querySelector("x-list"); | |
list.template = (item) => { | |
return `<div>${item.id} - ${item.name}</div>`; | |
}; | |
list.values = [ | |
{ | |
id: 1, | |
name: "Buy groceries", | |
}, | |
{ | |
id: 2, | |
name: "Clean up my desk", | |
}, | |
{ | |
id: 3, | |
name: "Do the laundry", | |
}, | |
]; | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Scoped slot with declarative allocation</title> | |
</head> | |
<body> | |
<x-list></x-list> | |
<script> | |
customElements.define( | |
"x-list", | |
class extends HTMLElement { | |
#values = []; | |
#tmpl; | |
constructor() { | |
super(); | |
const shadowRoot = this.attachShadow({ | |
mode: "open", | |
slotAssignment: "manual", | |
}); | |
this.shadowRoot.innerHTML = `<div></div>`; | |
} | |
set template(tmpl) { | |
this.#tmpl = tmpl; | |
this.#rerender(); | |
} | |
get template() { | |
return this.#tmpl; | |
} | |
set values(v) { | |
this.#values = v; | |
this.#rerender(); | |
} | |
get values() { | |
return this.#values; | |
} | |
#rerender() { | |
if (!this.#tmpl || !this.#values) { | |
return; | |
} | |
const container = this.shadowRoot.querySelector("div"); | |
const slots = []; | |
// Remove all the slots | |
while (container.firstChild) { | |
container.firstChild.remove(); | |
} | |
// Remove all the existing children | |
while (this.firstChild) { | |
this.firstChild.remove(); | |
} | |
// Render all the slots | |
for (let i = 0; i < this.#values.length; i++) { | |
const slot = document.createElement("slot"); | |
slots.push(slot); | |
container.appendChild(slot); | |
} | |
// Render all the scoped slotted content. | |
for (let i = 0; i < this.#values.length; i++) { | |
const tmpElm = document.createElement("template"); | |
tmpElm.innerHTML = this.#tmpl(this.#values[i]); | |
this.appendChild(tmpElm.content); | |
slots[i].assign(this.lastChild); | |
} | |
} | |
} | |
); | |
const list = document.querySelector("x-list"); | |
list.template = (item) => { | |
return `<div>${item.id} - ${item.name}</div>`; | |
}; | |
list.values = [ | |
{ | |
id: 1, | |
name: "Buy groceries", | |
}, | |
{ | |
id: 2, | |
name: "Clean up my desk", | |
}, | |
{ | |
id: 3, | |
name: "Do the laundry", | |
}, | |
]; | |
</script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="UTF-8" /> | |
<meta http-equiv="X-UA-Compatible" content="IE=edge" /> | |
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> | |
<title>Scoped slot with shadow allocation</title> | |
</head> | |
<body> | |
<x-list></x-list> | |
<script> | |
customElements.define( | |
"x-list", | |
class extends HTMLElement { | |
#values = []; | |
#tmpl; | |
constructor() { | |
super(); | |
const shadowRoot = this.attachShadow({ | |
mode: "open", | |
}); | |
this.shadowRoot.innerHTML = `<div></div>`; | |
} | |
set template(tmpl) { | |
this.#tmpl = tmpl; | |
this.#rerender(); | |
} | |
get template() { | |
return this.#tmpl; | |
} | |
set values(v) { | |
this.#values = v; | |
this.#rerender(); | |
} | |
get values() { | |
return this.#values; | |
} | |
#rerender() { | |
if (!this.#tmpl || !this.#values) { | |
return; | |
} | |
const container = this.shadowRoot.querySelector("div"); | |
// Remove all the existing children | |
while (this.firstChild) { | |
this.firstChild.remove(); | |
} | |
// Render all the scoped slotted content. | |
for (let i = 0; i < this.#values.length; i++) { | |
const tmpElm = document.createElement("template"); | |
tmpElm.innerHTML = this.#tmpl(this.#values[i]); | |
container.appendChild(tmpElm.content); | |
} | |
} | |
} | |
); | |
const list = document.querySelector("x-list"); | |
list.template = (item) => { | |
return `<div>${item.id} - ${item.name}</div>`; | |
}; | |
list.values = [ | |
{ | |
id: 1, | |
name: "Buy groceries", | |
}, | |
{ | |
id: 2, | |
name: "Clean up my desk", | |
}, | |
{ | |
id: 3, | |
name: "Do the laundry", | |
}, | |
]; | |
</script> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment