Using slots in WebComponents without using Shadow DOM
P粉936568533
P粉936568533 2024-03-28 21:59:05
0
1
430

I'm trying to build a WebComponent without using ShadowDOM - so far it's basically just working, but now I want to build a component that wraps other components, like using Angular's @ViewChild / @ViewChildren Same. (The library I use for rendering here is uhtl, similar to lit-html)

export class Dropdown extends HTMLElement {

    private open: boolean = false;

    static observedAttributes = ["open"]

    constructor() {
        super();
    }

    attributeChangedCallback(name: string, oldValue: string, newValue: string) {
        switch (name) {
            case "open":
                this.open = Boolean(newValue);
                break;
        }
        this.display()
    }

    connectedCallback() {
        this.display()
    }

    display = () => {
        render(this, html`
            <div>
                <slot name="item">

                </slot>
            </div>
        `)
    }

    static register = () => customElements.define("my-dropdown", Dropdown)

}

If I use this component now

Dropdown.register();


render(document.body, html`
    <my-dropdown open="true">
        <strong slot="item">test</strong>
    </my-dropdown>

`)

I look forward to seeing it

<my-dropdown>
    <div>
        <strong>test</test>
    </div>
</my-dropdown>

But the slot part doesn't work.

If I switch to ShadowDOM it works, but now I have to deal with ShadowDOM's sandboxing and I don't want to do that.

constructor() {
    super();
    this.attachShadow({mode: "open"})
}
display = () => {
    render(this.shadowRoot as Node, html`

Is it possible to make slots work without ShadowDOM? If not, is there a different way to get what is defined inside the component and use it inside the display?

<my-component>
    <div>some content here</div>
</my-component>

should be rendered as

<my-component>
    <header>
        random header
    </header>
    <section>
        <!-- my custom content -->
        <div>some content here</div>
    </section>
</my-component>

Any suggestions?

P粉936568533
P粉936568533

reply all(1)
P粉696605833

No, <slot> is part of the ShadowDOM API

You can fake it, but since there is no shadowDOM, you have to store that content somewhere else.
Probably your <template> that reads and parses the (light) DOM content.

This is a bunch of DOM mutations.
It might be easier to learn to use ShadowDOM styles:

  • CSS Properties
  • Inheritable styles
  • ::part
  • Constructible stylesheet
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template