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());
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>
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
Any whitespace and linebreaks in your HTML IS slotted to the default <slot></slot>
!