Is it possible to automatically or programmatically slot nested web components or elements of a specific type without having to specify the slot
attribute on them?
Consider some structure like this:
<parent-element>
<child-element>Child 1</child-element>
<child-element>Child 2</child-element>
<p>Content</p>
</parent-element>
With the <parent-element>
having a Shadow DOM like this:
<div id="child-elements">
<slot name="child-elements">
<child-element>Default child</child-element>
</slot>
</div>
<div id="content">
<slot></slot>
</div>
The expected result is:
<parent-element>
<#shadow-root>
<div id="child-elements">
<slot name="child-elements">
<child-element>Child 1</child-element>
<child-element>Child 2</child-element>
</slot>
</div>
<div id="content">
<slot>
<p>Content</p>
</slot>
</div>
</parent-element>
In words, I want to enforce that <child-element>
s are only allowed within a <parent-element>
similar to <td>
elements only being allowed within a <tr>
element. And I want them to be placed within the <slot name="child-elements">
element. Having to specify a slot
attribute on each of them to place them within a specific slot of the <parent-element>
seems redundant.
At the same time, the rest of the content within the <parent-element>
should automatically be slotted into the second <slot>
element.
I've first searched for a way to define this when registering the parent element, though CustomElementRegistry.define()
currently only supports extends
as option.
Then I thought, maybe there's a function allowing to slot the elements manually, i.e. something like childElement.slot('child-elements')
, but that doesn't seem to exist.
I've then tried to achive this programmatically in the constructor of the parent element like this:
constructor() {
super();
this.attachShadow({mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
const childElements = this.getElementsByTagName('child-element');
const childElementSlot = this.shadowRoot.querySelector('[name="child-elements"]');
for (let i = 0; i < childElements.length; i++) {
childElementSlot.appendChild(childElements[i]);
}
}
Though this doesn't move the child elements to the <slot name="child-elements">
, so all of them still get slotted in the second <slot>
element.