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.