Is there an alternative to declaring a slot name in light DOM?

2.5k views Asked by At

In shadow DOM v0 developers were not required to know as much about the internal implementation of how/where light DOM content was to be placed in a component's shadow dom.

The v0 specification matched the current behavior of built-in components like <select> and <option> where the consumer doesn't care as much where specifically their element content would be placed. Instead, the shadow DOM would automatically pick up the elements that match selectors specified in the select attribute on a <content> tag and place them in the correct location inside the shadow tree. This required less boilerplate on the consuming developer's code.

In v1 you need to know the slot name specifically. Mimicking the same example previously mentioned with <select>, I would need to use something like <option slot="option"> where the slot attribute value specifies where to put the current element. I would also be allowed to add elements that were not intended to be included in that slot like <table slot="option">.

In summary, my concerns are:

  1. Needing to specify extra information every time I use the webcomponent
  2. Having the ability to add invalid elements to the wrong shadow DOM location and have that cause unpredictable side-effects

In shadow DOM v1 is there a way to get the old behavior of <content select="option"></content> where a child has to match a specific selector or it is discarded? If not, does anyone know why specifically such a big breaking change was made?

Example 1 (v0 specification)

index.html

<my-component>
    <my-child-component>Text</my-child-component>
    <wrong-child-component>Wrong</wrong-child-component>
</my-component>

component.html (shadow DOM)

<div>
    <content select="my-child-component"></component>
</div>

resulting DOM

<my-component>
    #shadow-root
        <div>
            <my-child-component>Text</my-child-component>
        </div>
<my-component>

Example 2 (v1 specification)

index.html

<my-component>
    <my-child-component slot="child-slot">Text</my-child>
    <wrong-child-component slot="child-slot">Wrong</wrong-child-component>
</my-component>

component.html (shadow DOM)

<div>
    <slot name="child-slot"></slot>
</div>

resulting DOM

<my-component>
    #shadow-root
        <div>
            <my-child-component>Text</my-child-component>
            <wrong-child-component>Wrong</wrong-child-component>
        </div>
<my-component>
2

There are 2 answers

11
a1626 On

For v1 there will be no other alternate to slot(as far as i have read). But i still don't see the problem. Just like content you can use nameless slot also.

Here's an example for Polymer's 2.0 migration guide

<!-- element template -->
<dom-module id="my-el">
  <template>
   ...
   <h2>
     <slot name="title"></slot>
   </h2>
   <div>
     <slot></slot>
   </div>
 </template>
</dom-module>

...
<!-- usage -->
<my-el>
   <span slot="title">Mr. Darcy</span>
   <span>Fun at parties.</span>
</my-el>

Here's one of the discussion on github discussing proposing using slot over content and just to list few advantages of slot over content

Default slot versus default insertion point. In v0, a default insertion point (one without a select attribute) consumes all nodes not matched by a previous insertion point. In v1, a default slot (one without a name attribute) only matches content with no slot attribute. In other words, a node with a slot attribute is never distributed to the default slot.

Though it has few disadvantages over content also but atleast for now vendors have agreed that slot is the way forward.

0
Supersharp On

To filter the right elements, maybe you can use the ::slotted( selector ) pseudo-element in your Shadow DOM CSS styles:

<style>
    ::slotted( :not( option ) )
    {
        display: none;
    }
</style>
<slot></slot>

...will display only <option> elements.