How to programmatically create a slot and slot a HTMLElement into it?

825 Views Asked by At

I'd like to, without using HTML, create a slot and slot an element into it. I tried the following and a few variations but no luck. What am I doing wrong? Why is slot.assignedNodes() returning an empty array after I assigned the element?

const element = document.createElement('div');
const slot = document.createElement('slot');
const slotted = document.createElement('span');

document.body.append(element);
element.attachShadow({ mode: 'open', slotAssignment: 'manual'});

element.shadowRoot.append(slot);
element.shadowRoot.append(slotted);

slot.assign(slotted);
console.log(slot.assignedNodes());

1

There are 1 best solutions below

0
Danny '365CSI' Engelman On BEST ANSWER

Your problem is here:

element.shadowRoot.append(slot);
element.shadowRoot.append(slotted);

You are assigning slotted to the same shadowDOM the <slot> is in.
It should go to lightDOM with: element.append(slotted)


I rewrote your code so (I hope) its clearer

const DIV = document.createElement('DIV');
DIV.attachShadow({ mode: 'open', slotAssignment: 'manual'});

const SLOT = document.createElement('SLOT');
DIV.shadowRoot.append( SLOT ); // Create SLOT in SHADOWDOM

document.body.append( DIV );

const SPAN = document.createElement('SPAN');
SPAN.innerHTML = "I AM SLOTTED";

DIV.append(SPAN); // put me in LIGHTDOM!

SLOT.assign( SPAN ); // only works because of slotAssignment:"manual" !!

console.log(SLOT.assignedNodes());

Without slotAssignment:"manual" you do not need SLOT.assign(SPAN) because lightDOM content will automagically be slotted to the default unnamed <slot>

With standard slot behavior

const DIV = document.createElement('DIV');
DIV.attachShadow({ mode: 'open'});

const SLOT1 = document.createElement('SLOT'); // default slot
const SLOT2 = document.createElement('SLOT'); // slot name='title' !
SLOT2.name = "title";
DIV.shadowRoot.append( SLOT1 , SLOT2 ); // Create SLOTs in SHADOWDOM

document.body.append( DIV );

const SPAN = document.createElement('SPAN');
SPAN.slot = "title";
SPAN.innerHTML = "I AM SLOTTED in the SLOT name='title'";

DIV.append(SPAN); // put me in LIGHTDOM!

console.log(SLOT1.assignedNodes()); // nothing assigned to default slot